[libcxx-commits] [libcxx] [libc++][string] P3044R2: sub-`string_view` from `string` (PR #147095)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 6 09:37:20 PDT 2025


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/147095

>From 0510c784394a21e0a1ec06e15588848912dc568b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 18:22:03 +0300
Subject: [PATCH 01/13] WIP [libc++][string] P3044R2: sub-`string_view` from
 `string`

Implements [P3044R2](https://wg21.link/P3044R2)

-  https://github.com/cplusplus/draft/pull/7975
---
 libcxx/include/string                         |   9 +
 libcxx/include/string_view                    |   8 +
 .../string.ops/string_substr/subview.pass.cpp |  33 ++++
 .../string.view.ops/substr.pass.cpp           | 125 --------------
 .../string.view.ops/substr_subview.pass.cpp   | 158 ++++++++++++++++++
 5 files changed, 208 insertions(+), 125 deletions(-)
 create mode 100644 libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
 delete mode 100644 libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
 create mode 100644 libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp

diff --git a/libcxx/include/string b/libcxx/include/string
index 98297d04d0c61..7e8d8fac9f753 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -280,6 +280,8 @@ public:
     basic_string substr(size_type pos = 0, size_type n = npos) const;                           // constexpr in C++20, removed in C++23
     basic_string substr(size_type pos = 0, size_type n = npos) const&;                          // since C++23
     constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;                    // since C++23
+    constexpr basic_string_view<charT, traits> subview(size_type pos = 0,
+                                                       size_type n = npos) const;               // since C++26
     void swap(basic_string& str)
         noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
                  allocator_traits<allocator_type>::is_always_equal::value);                     // C++17, constexpr since C++20
@@ -1752,6 +1754,13 @@ public:
   }
 #  endif
 
+#  if _LIBCPP_STD_VER >= 26
+  _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT, _Traits>
+  subview(size_type __pos = 0, size_type __n = npos) const {
+    return basic_string_view<_CharT, _Traits>(*this).subview(__pos, __n);
+  }
+#  endif
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str)
 #  if _LIBCPP_STD_VER >= 14
       _NOEXCEPT;
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index f86b2722aca6c..952d44123622b 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -130,6 +130,8 @@ namespace std {
       size_type copy(charT* s, size_type n, size_type pos = 0) const;  // constexpr in C++20
 
       constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
+      constexpr basic_string_view subview(size_type pos = 0,
+                                          size_type n = npos) const;      // freestanding-deleted, since C++26
       constexpr int compare(basic_string_view s) const noexcept;
       constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
       constexpr int compare(size_type pos1, size_type n1,
@@ -465,6 +467,12 @@ public:
                           : basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
   }
 
+#  if _LIBCPP_STD_VER >= 26
+  _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
+    return this->substr(__pos, __n);
+  }
+#  endif
+
   _LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
     size_type __rlen = std::min(size(), __sv.size());
     int __retval     = _Traits::compare(data(), __sv.data(), __rlen);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
new file mode 100644
index 0000000000000..65418dcb4d7be
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <string>
+
+// constexpr basic_string_view<_CharT, _Traits> subview(size_type __pos = 0, size_type __n = npos) const;
+
+#include <cassert>
+#include <string>
+
+constexpr bool test() {
+  std::string s{"Hello cruel world!"};
+  auto sub = s.subview(6);
+  assert(sub == "cruel world!");
+  auto subsub = sub.subview(0, 5);
+  assert(subsub == "cruel");
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
deleted file mode 100644
index 62b0259c175f8..0000000000000
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
+++ /dev/null
@@ -1,125 +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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: !stdlib=libc++ && (c++03 || c++11 || c++14)
-
-// <string_view>
-
-// constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
-
-// Throws: out_of_range if pos > size().
-// Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
-// Returns: basic_string_view(data()+pos, rlen).
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <stdexcept>
-#include <string_view>
-
-#include "test_macros.h"
-
-template <typename CharT>
-void test1(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
-  std::basic_string_view<CharT> sv1;
-#ifdef TEST_HAS_NO_EXCEPTIONS
-  if (pos > sv.size())
-    return; // would throw if exceptions were enabled
-  sv1 = sv.substr(pos, n);
-#else
-  try {
-    sv1 = sv.substr(pos, n);
-    assert(pos <= sv.size());
-  } catch (const std::out_of_range&) {
-    assert(pos > sv.size());
-    return;
-  }
-#endif
-  const std::size_t rlen = std::min(n, sv.size() - pos);
-  assert(sv1.size() == rlen);
-  for (std::size_t i = 0; i < rlen; ++i)
-    assert(sv[pos + i] == sv1[i]);
-}
-
-template <typename CharT>
-void test(const CharT* s) {
-  typedef std::basic_string_view<CharT> string_view_t;
-
-  string_view_t sv1(s);
-
-  test1(sv1, 0, 0);
-  test1(sv1, 1, 0);
-  test1(sv1, 20, 0);
-  test1(sv1, sv1.size(), 0);
-
-  test1(sv1, 0, 3);
-  test1(sv1, 2, 3);
-  test1(sv1, 100, 3);
-
-  test1(sv1, 0, string_view_t::npos);
-  test1(sv1, 2, string_view_t::npos);
-  test1(sv1, sv1.size(), string_view_t::npos);
-
-  test1(sv1, sv1.size() + 1, 0);
-  test1(sv1, sv1.size() + 1, 1);
-  test1(sv1, sv1.size() + 1, string_view_t::npos);
-}
-
-int main(int, char**) {
-  test("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  test("ABCDE");
-  test("a");
-  test("");
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test(L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  test(L"ABCDE");
-  test(L"a");
-  test(L"");
-#endif
-
-#if TEST_STD_VER >= 11
-  test(u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  test(u"ABCDE");
-  test(u"a");
-  test(u"");
-
-  test(U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  test(U"ABCDE");
-  test(U"a");
-  test(U"");
-#endif
-
-#if TEST_STD_VER > 11
-  {
-    constexpr std::string_view sv1{"ABCDE", 5};
-
-    {
-      constexpr std::string_view sv2 = sv1.substr(0, 3);
-      static_assert(sv2.size() == 3, "");
-      static_assert(sv2[0] == 'A', "");
-      static_assert(sv2[1] == 'B', "");
-      static_assert(sv2[2] == 'C', "");
-    }
-
-    {
-      constexpr std::string_view sv2 = sv1.substr(3, 0);
-      static_assert(sv2.size() == 0, "");
-    }
-
-    {
-      constexpr std::string_view sv2 = sv1.substr(3, 3);
-      static_assert(sv2.size() == 2, "");
-      static_assert(sv2[0] == 'D', "");
-      static_assert(sv2[1] == 'E', "");
-    }
-  }
-#endif
-
-  return 0;
-}
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp
new file mode 100644
index 0000000000000..c40c771db4bae
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp
@@ -0,0 +1,158 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: !stdlib=libc++ && (c++03 || c++11 || c++14)
+
+// <string_view>
+
+// constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
+// constexpr basic_string_view subview(size_type pos = 0,
+//                                     size_type n = npos) const;      // freestanding-deleted
+
+// subview is alternative name of substr
+
+// Throws: out_of_range if pos > size().
+// Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
+// Returns: basic_string_view(data()+pos, rlen).
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <stdexcept>
+#include <string_view>
+
+#include "test_macros.h"
+
+template <typename CharT>
+struct Test {
+  typedef std::basic_string_view<CharT> (std::basic_string_view<CharT>::*Sub)(
+      typename std::basic_string_view<CharT>::size_type, typename std::basic_string_view<CharT>::size_type) const;
+};
+
+template <typename CharT>
+void testDetail(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub, std::size_t n, size_t pos) {
+  (void)testSub; // Avoid unused parameter warning
+  std::basic_string_view<CharT> sv1;
+#ifdef TEST_HAS_NO_EXCEPTIONS
+  if (pos > sv.size())
+    return; // would throw if exceptions were enabled
+  sv1 = (sv.*testSub)(pos, n);
+#else
+  try {
+    sv1 = (sv.*testSub)(pos, n);
+    assert(pos <= sv.size());
+  } catch (const std::out_of_range&) {
+    assert(pos > sv.size());
+    return;
+  }
+#endif
+  const std::size_t rlen = std::min(n, sv.size() - pos);
+  assert(sv1.size() == rlen);
+  for (std::size_t i = 0; i < rlen; ++i)
+    assert(sv[pos + i] == sv1[i]);
+}
+
+template <typename CharT>
+void testCases(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub) {
+  testDetail(sv, testSub, 0, 0);
+  testDetail(sv, testSub, 1, 0);
+  testDetail(sv, testSub, 20, 0);
+  testDetail(sv, testSub, sv.size(), 0);
+
+  testDetail(sv, testSub, 100, 3);
+
+  testDetail(sv, testSub, 0, std::basic_string_view<CharT>::npos);
+  testDetail(sv, testSub, 2, std::basic_string_view<CharT>::npos);
+  testDetail(sv, testSub, sv.size(), std::basic_string_view<CharT>::npos);
+
+  testDetail(sv, testSub, sv.size() + 1, 0);
+  testDetail(sv, testSub, sv.size() + 1, 1);
+  testDetail(sv, testSub, sv.size() + 1, std::basic_string_view<CharT>::npos);
+}
+
+template <typename CharT>
+void testSubs(const CharT* s) {
+  std::basic_string_view<CharT> sv(s);
+
+  testCases(sv, &std::basic_string_view<CharT>::substr);
+#if TEST_STD_VER >= 26
+  testCases(sv, &std::basic_string_view<CharT>::subview);
+#endif // TEST_STD_VER >= 26
+}
+
+void test() {
+  testSubs("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  testSubs("ABCDE");
+  testSubs("a");
+  testSubs("");
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  testSubs(
+      L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  testSubs(L"ABCDE");
+  testSubs(L"a");
+  testSubs(L"");
+#endif
+
+#if TEST_STD_VER >= 11
+  testSubs(
+      u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  testSubs(u"ABCDE");
+  testSubs(u"a");
+  testSubs(u"");
+
+  testSubs(
+      U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  testSubs(U"ABCDE");
+  testSubs(U"a");
+  testSubs(U"");
+#endif
+}
+
+#if TEST_STD_VER >= 14
+template <typename Test<char>::Sub TestSub>
+constexpr void testConstexprDetail() {
+  constexpr std::string_view sv{"ABCDE", 5};
+  {
+    constexpr std::string_view sv2 = (sv.*TestSub)(0, 3);
+
+    static_assert(sv2.size() == 3, "");
+    static_assert(sv2[0] == 'A', "");
+    static_assert(sv2[1] == 'B', "");
+    static_assert(sv2[2] == 'C', "");
+  }
+
+  {
+    constexpr std::string_view sv2 = (sv.*TestSub)(3, 0);
+    static_assert(sv2.size() == 0, "");
+  }
+
+  {
+    constexpr std::string_view sv2 = (sv.*TestSub)(3, 3);
+    static_assert(sv2.size() == 2, "");
+    static_assert(sv2[0] == 'D', "");
+    static_assert(sv2[1] == 'E', "");
+  }
+}
+
+void test_constexpr() {
+  testConstexprDetail<&std::string_view::substr>();
+#  if TEST_STD_VER >= 26
+  testConstexprDetail<&std::string_view::subview>();
+#  endif
+}
+#endif
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 14
+  test_constexpr();
+#endif
+
+  return 0;
+}

>From ad5e4107304b3169b54d2cc6904b66734b8512e1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 21:26:04 +0300
Subject: [PATCH 02/13] Renamed test

---
 ...ubstr_subview.pass.cpp => substr.pass.cpp} | 43 +++++++++----------
 .../string.view.ops/subview.pass.cpp          | 20 +++++++++
 2 files changed, 41 insertions(+), 22 deletions(-)
 rename libcxx/test/std/strings/string.view/string.view.ops/{substr_subview.pass.cpp => substr.pass.cpp} (77%)
 create mode 100644 libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp

diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
similarity index 77%
rename from libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp
rename to libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
index c40c771db4bae..02755985ead70 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr_subview.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
@@ -34,17 +34,16 @@ struct Test {
       typename std::basic_string_view<CharT>::size_type, typename std::basic_string_view<CharT>::size_type) const;
 };
 
-template <typename CharT>
-void testDetail(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub, std::size_t n, size_t pos) {
-  (void)testSub; // Avoid unused parameter warning
+template <typename CharT, typename Test<CharT>::Sub TestSub>
+void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
   std::basic_string_view<CharT> sv1;
 #ifdef TEST_HAS_NO_EXCEPTIONS
   if (pos > sv.size())
     return; // would throw if exceptions were enabled
-  sv1 = (sv.*testSub)(pos, n);
+  sv1 = (sv.*TestSub)(pos, n);
 #else
   try {
-    sv1 = (sv.*testSub)(pos, n);
+    sv1 = (sv.*TestSub)(pos, n);
     assert(pos <= sv.size());
   } catch (const std::out_of_range&) {
     assert(pos > sv.size());
@@ -57,31 +56,31 @@ void testDetail(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub test
     assert(sv[pos + i] == sv1[i]);
 }
 
-template <typename CharT>
-void testCases(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub) {
-  testDetail(sv, testSub, 0, 0);
-  testDetail(sv, testSub, 1, 0);
-  testDetail(sv, testSub, 20, 0);
-  testDetail(sv, testSub, sv.size(), 0);
+template <typename CharT, typename Test<CharT>::Sub TestSub>
+void testCases(const CharT* s) {
+  std::basic_string_view<CharT> sv(s);
 
-  testDetail(sv, testSub, 100, 3);
+  testDetail<CharT, TestSub>(sv, 0, 0);
+  testDetail<CharT, TestSub>(sv, 1, 0);
+  testDetail<CharT, TestSub>(sv, 20, 0);
+  testDetail<CharT, TestSub>(sv, sv.size(), 0);
 
-  testDetail(sv, testSub, 0, std::basic_string_view<CharT>::npos);
-  testDetail(sv, testSub, 2, std::basic_string_view<CharT>::npos);
-  testDetail(sv, testSub, sv.size(), std::basic_string_view<CharT>::npos);
+  testDetail<CharT, TestSub>(sv, 100, 3);
 
-  testDetail(sv, testSub, sv.size() + 1, 0);
-  testDetail(sv, testSub, sv.size() + 1, 1);
-  testDetail(sv, testSub, sv.size() + 1, std::basic_string_view<CharT>::npos);
+  testDetail<CharT, TestSub>(sv, 0, std::basic_string_view<CharT>::npos);
+  testDetail<CharT, TestSub>(sv, 2, std::basic_string_view<CharT>::npos);
+  testDetail<CharT, TestSub>(sv, sv.size(), std::basic_string_view<CharT>::npos);
+
+  testDetail<CharT, TestSub>(sv, sv.size() + 1, 0);
+  testDetail<CharT, TestSub>(sv, sv.size() + 1, 1);
+  testDetail<CharT, TestSub>(sv, sv.size() + 1, std::basic_string_view<CharT>::npos);
 }
 
 template <typename CharT>
 void testSubs(const CharT* s) {
-  std::basic_string_view<CharT> sv(s);
-
-  testCases(sv, &std::basic_string_view<CharT>::substr);
+  testCases<CharT, &std::basic_string_view<CharT>::substr>(s);
 #if TEST_STD_VER >= 26
-  testCases(sv, &std::basic_string_view<CharT>::subview);
+  testCases<CharT, &std::basic_string_view<CharT>::subview>(s);
 #endif // TEST_STD_VER >= 26
 }
 
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
new file mode 100644
index 0000000000000..fec258eef4546
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <string_view>
+
+// constexpr basic_string_view subview(size_type pos = 0,
+//                                     size_type n = npos) const;      // freestanding-deleted
+
+int main(int, char**) {
+  // This test is intentionally empty because subview is an alias for substr
+  // and is tested in substr.pass.cpp.
+  return 0;
+}

>From 14162bf3567254c5f4dd8088cd8f8cfeadbf2fe6 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 22 Jul 2025 22:01:54 +0300
Subject: [PATCH 03/13] LLVM22

---
 libcxx/docs/FeatureTestMacroTable.rst         |  2 ++
 libcxx/docs/ReleaseNotes/22.rst               |  1 +
 libcxx/docs/Status/Cxx2cPapers.csv            |  2 +-
 libcxx/include/version                        |  2 ++
 .../string.version.compile.pass.cpp           | 30 +++++++++++++++++++
 .../string_view.version.compile.pass.cpp      | 30 +++++++++++++++++++
 .../version.version.compile.pass.cpp          | 30 +++++++++++++++++++
 .../generate_feature_test_macro_components.py |  5 ++++
 8 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 61805726a4ff0..63af1ffd77ca4 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -404,6 +404,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_string_resize_and_overwrite``                  ``202110L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_string_subview``                               ``202506L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_to_underlying``                                ``202102L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_tuple_like``                                   *unimplemented*
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 15bf46d44b07f..9361dc0ee8753 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -39,6 +39,7 @@ Implemented Papers
 ------------------
 
 - P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release)
+- P3044R2: sub-``string_view`` from ``string`` (`Github <https://github.com/llvm/llvm-project/issues/148140>`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index febb0c176f9c4..d954c4b9bbdec 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -129,7 +129,7 @@
 "`P3179R9 <https://wg21.link/P3179R9>`__","Parallel Range Algorithms","2025-06 (Sofia)","","",""
 "`P3709R2 <https://wg21.link/P3709R2>`__","Reconsider parallel ``ranges::rotate_copy`` and ``ranges::reverse_copy``","2025-06 (Sofia)","","",""
 "`P3641R0 <https://wg21.link/P3641R0>`__","Rename ``std::observable`` to ``std::observable_checkpoint``, and add a feature-test macro","2025-06 (Sofia)","","",""
-"`P3044R2 <https://wg21.link/P3044R2>`__","sub-``string_view`` from ``string``","2025-06 (Sofia)","","",""
+"`P3044R2 <https://wg21.link/P3044R2>`__","sub-``string_view`` from ``string``","2025-06 (Sofia)","|Complete|","22",""
 "`P2876R3 <https://wg21.link/P2876R3>`__","Proposal to extend ``std::simd`` with more constructors and accessors","2025-06 (Sofia)","","",""
 "`P3480R6 <https://wg21.link/P3480R6>`__","``std::simd`` is a range","2025-06 (Sofia)","","",""
 "`P2664R11 <https://wg21.link/P2664R11>`__","Extend ``std::simd`` with permutation API","2025-06 (Sofia)","","",""
diff --git a/libcxx/include/version b/libcxx/include/version
index d98049bd57046..dd874c7d50c74 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -245,6 +245,7 @@ __cpp_lib_starts_ends_with                              201711L <string> <string
 __cpp_lib_stdatomic_h                                   202011L <stdatomic.h>
 __cpp_lib_string_contains                               202011L <string> <string_view>
 __cpp_lib_string_resize_and_overwrite                   202110L <string>
+__cpp_lib_string_subview                                202506L <string> <string_view>
 __cpp_lib_string_udls                                   201304L <string>
 __cpp_lib_string_view                                   202403L <string> <string_view>
                                                         201803L // C++20
@@ -535,6 +536,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_stdatomic_h                          202011L
 # define __cpp_lib_string_contains                      202011L
 # define __cpp_lib_string_resize_and_overwrite          202110L
+# define __cpp_lib_string_subview                       202506L
 # define __cpp_lib_to_underlying                        202102L
 // # define __cpp_lib_tuple_like                           202207L
 # define __cpp_lib_unreachable                          202202L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
index 7236d5d7f2aca..c69c8ed59fb61 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
@@ -60,6 +60,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifdef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should not be defined before c++14"
 #  endif
@@ -114,6 +118,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++14"
 #  endif
@@ -177,6 +185,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++17"
 #  endif
@@ -261,6 +273,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++20"
 #  endif
@@ -354,6 +370,13 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++23"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++23"
 #  endif
@@ -456,6 +479,13 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++26"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++26"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++26"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++26"
 #  endif
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
index c7bafb0bf059c..ed13f392b1b7f 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
@@ -40,6 +40,10 @@
 #    error "__cpp_lib_string_contains should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifdef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should not be defined before c++17"
 #  endif
@@ -66,6 +70,10 @@
 #    error "__cpp_lib_string_contains should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifdef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should not be defined before c++17"
 #  endif
@@ -92,6 +100,10 @@
 #    error "__cpp_lib_string_contains should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should be defined in c++17"
 #  endif
@@ -136,6 +148,10 @@
 #    error "__cpp_lib_string_contains should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should be defined in c++20"
 #  endif
@@ -183,6 +199,13 @@
 #    error "__cpp_lib_string_contains should have the value 202011L in c++23"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++23"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should be defined in c++23"
 #  endif
@@ -239,6 +262,13 @@
 #    error "__cpp_lib_string_contains should have the value 202011L in c++26"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++26"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++26"
+#  endif
+
 #  ifndef __cpp_lib_string_view
 #    error "__cpp_lib_string_view should be defined in c++26"
 #  endif
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 962688e06188a..0df86fbb825e4 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
@@ -820,6 +820,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifdef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should not be defined before c++14"
 #  endif
@@ -1775,6 +1779,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++14"
 #  endif
@@ -2916,6 +2924,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++17"
 #  endif
@@ -4330,6 +4342,10 @@
 #    error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++20"
 #  endif
@@ -5978,6 +5994,13 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++23"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++23"
 #  endif
@@ -7947,6 +7970,13 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++26"
 #  endif
 
+#  ifndef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should be defined in c++26"
+#  endif
+#  if __cpp_lib_string_subview != 202506L
+#    error "__cpp_lib_string_subview should have the value 202506L in c++26"
+#  endif
+
 #  ifndef __cpp_lib_string_udls
 #    error "__cpp_lib_string_udls should be defined in c++26"
 #  endif
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index fe175fd758726..75cc8705ecffb 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1337,6 +1337,11 @@ def add_version_header(tc):
             "values": {"c++23": 202110},
             "headers": ["string"],
         },
+        {
+            "name": "__cpp_lib_string_subview",
+            "values": {"c++23": 202506},
+            "headers": ["string", "string_view"],
+        },
         {
             "name": "__cpp_lib_string_udls",
             "values": {"c++14": 201304},

>From f9efc16976cf10bdd2941e0d5061db5caa793005 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 23 Jul 2025 01:21:11 +0300
Subject: [PATCH 04/13] Updated test

---
 .../string.ops/string_substr/subview.pass.cpp | 47 +++++++++++++++++--
 1 file changed, 42 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 65418dcb4d7be..4fd2a4ceb5f7a 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -15,12 +15,49 @@
 #include <cassert>
 #include <string>
 
+#include "asan_testing.h"
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#define CS(S) MAKE_CSTRING(CharT, S)
+
+template <typename CharT, typename TraitsT, typename AllocT>
+constexpr void test() {
+  std::basic_string<CharT, TraitsT, AllocT> s{CS("Hello cruel world!"), AllocT{}};
+
+  std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6);
+  assert(sv == CS("cruel world!"));
+
+  std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) subsv = sv.subview(0, 5);
+  assert(subsv == CS("cruel"));
+}
+
+template <typename CharT>
+constexpr void test() {
+  test<CharT, std::char_traits<CharT>, std::allocator<CharT>>();
+  test<CharT, std::char_traits<CharT>, min_allocator<CharT>>();
+  test<CharT, std::char_traits<CharT>, safe_allocator<CharT>>();
+  test<CharT, std::char_traits<CharT>, test_allocator<CharT>>();
+
+  test<CharT, constexpr_char_traits<CharT>, std::allocator<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>, min_allocator<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>, safe_allocator<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>();
+}
+
 constexpr bool test() {
-  std::string s{"Hello cruel world!"};
-  auto sub = s.subview(6);
-  assert(sub == "cruel world!");
-  auto subsub = sub.subview(0, 5);
-  assert(subsub == "cruel");
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+  test<char16_t>();
+  test<char32_t>();
 
   return true;
 }

>From 3dbebaee031930e6658b8748cd670f566a4ccabd Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 23 Jul 2025 09:03:19 +0300
Subject: [PATCH 05/13] Fix the test!!!

---
 .../string.ops/string_substr/subview.pass.cpp | 28 +++++++++++++++----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 4fd2a4ceb5f7a..63beedf829039 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -15,7 +15,6 @@
 #include <cassert>
 #include <string>
 
-#include "asan_testing.h"
 #include "constexpr_char_traits.h"
 #include "make_string.h"
 #include "min_allocator.h"
@@ -28,11 +27,30 @@ template <typename CharT, typename TraitsT, typename AllocT>
 constexpr void test() {
   std::basic_string<CharT, TraitsT, AllocT> s{CS("Hello cruel world!"), AllocT{}};
 
-  std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6);
-  assert(sv == CS("cruel world!"));
+  { // With a default position and a character length.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview();
+    assert(sv == CS("Hello cruel world!"));
+  }
 
-  std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) subsv = sv.subview(0, 5);
-  assert(subsv == CS("cruel"));
+  { // With a explict position and a character length.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6, 5);
+    assert(sv == CS("cruel"));
+  }
+
+  { // From the beginning of the string with a explicit character length.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, 5);
+    assert(sv == CS("Hello"));
+  }
+
+  { // To the end of string with the default character length.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(12);
+    assert(sv == CS("world!"));
+  }
+
+  { // From the beginning to the end of the string with explicit values.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, s.size());
+    assert(sv == CS("Hello cruel world!"));
+  }
 }
 
 template <typename CharT>

>From 43e3c15add04ea529f48043f5c50fecab3eddc08 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 2 Aug 2025 07:35:28 +0300
Subject: [PATCH 06/13] Address review comments

---
 .../string.ops/string_substr/subview.pass.cpp | 40 +++++++++++++++++++
 .../string.view.ops/substr.pass.cpp           |  2 +-
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 63beedf829039..20443f2f479cf 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -14,6 +14,7 @@
 
 #include <cassert>
 #include <string>
+#include <utility>
 
 #include "constexpr_char_traits.h"
 #include "make_string.h"
@@ -29,28 +30,67 @@ constexpr void test() {
 
   { // With a default position and a character length.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview();
+
     assert(sv == CS("Hello cruel world!"));
+    // Also check if subview() is a const-qualified.
+    assert(std::as_const(s).subview() == CS("Hello cruel world!"));
   }
 
   { // With a explict position and a character length.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6, 5);
+
     assert(sv == CS("cruel"));
   }
 
   { // From the beginning of the string with a explicit character length.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, 5);
+
     assert(sv == CS("Hello"));
   }
 
   { // To the end of string with the default character length.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(12);
+
     assert(sv == CS("world!"));
   }
 
   { // From the beginning to the end of the string with explicit values.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, s.size());
+
     assert(sv == CS("Hello cruel world!"));
   }
+
+  // Test if exceptions are thrown correctly.
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  if (!std::is_constant_evaluated()) {
+    { // With a position that is out of range.
+      try {
+        s.subview(s.size() + 1);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
+
+    { // With a position that is out of range and a 0 character length.
+      try {
+        s.subview(s.size() + 1, 0);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
+
+    { // With a position that is out of range and a some character length.
+      try {
+        s.subview(s.size() + 1, 1);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
+  }
+#endif
 }
 
 template <typename CharT>
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
index 02755985ead70..8f488cdf54c6e 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
@@ -81,7 +81,7 @@ void testSubs(const CharT* s) {
   testCases<CharT, &std::basic_string_view<CharT>::substr>(s);
 #if TEST_STD_VER >= 26
   testCases<CharT, &std::basic_string_view<CharT>::subview>(s);
-#endif // TEST_STD_VER >= 26
+#endif
 }
 
 void test() {

>From b6c564a724b30fade5a63cdb0160b999d73ec6d5 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 08:36:13 +0300
Subject: [PATCH 07/13] Addressed comments

---
 .../string.ops/string_substr/subview.pass.cpp |  35 ++-
 .../string.view.ops/substr.pass.cpp           | 219 ++++++++++++------
 2 files changed, 161 insertions(+), 93 deletions(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 20443f2f479cf..ab74624ccb393 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -29,6 +29,8 @@ constexpr void test() {
   std::basic_string<CharT, TraitsT, AllocT> s{CS("Hello cruel world!"), AllocT{}};
 
   { // With a default position and a character length.
+
+    // Check it the return type of subview() is correct.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview();
 
     assert(sv == CS("Hello cruel world!"));
@@ -36,28 +38,19 @@ constexpr void test() {
     assert(std::as_const(s).subview() == CS("Hello cruel world!"));
   }
 
-  { // With a explict position and a character length.
-    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6, 5);
-
-    assert(sv == CS("cruel"));
-  }
-
-  { // From the beginning of the string with a explicit character length.
-    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, 5);
+  { // Check with different position and length.
 
-    assert(sv == CS("Hello"));
-  }
-
-  { // To the end of string with the default character length.
-    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(12);
+    // With a explict position and a character length.
+    assert(s.subview(6, 5) == CS("cruel"));
 
-    assert(sv == CS("world!"));
-  }
+    // From the beginning of the string with a explicit character length.
+    assert(sv = s.subview(0, 5) == CS("Hello"));
 
-  { // From the beginning to the end of the string with explicit values.
-    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, s.size());
+    // To the end of string with the default character length.
+    assert(subview(12) == CS("world!"));
 
-    assert(sv == CS("Hello cruel world!"));
+    // From the beginning to the end of the string with explicit values.
+    assert(subview(0, s.size() == CS("Hello cruel world!"));
   }
 
   // Test if exceptions are thrown correctly.
@@ -68,7 +61,7 @@ constexpr void test() {
         s.subview(s.size() + 1);
         assert(false && "Expected std::out_of_range exception");
       } catch (const std::out_of_range&) {
-        // Expected exception
+        // Expected exception...
       }
     }
 
@@ -77,7 +70,7 @@ constexpr void test() {
         s.subview(s.size() + 1, 0);
         assert(false && "Expected std::out_of_range exception");
       } catch (const std::out_of_range&) {
-        // Expected exception
+        // Expected exception...
       }
     }
 
@@ -86,7 +79,7 @@ constexpr void test() {
         s.subview(s.size() + 1, 1);
         assert(false && "Expected std::out_of_range exception");
       } catch (const std::out_of_range&) {
-        // Expected exception
+        // Expected exception...
       }
     }
   }
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
index 8f488cdf54c6e..6ed46452365a5 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
@@ -20,36 +20,41 @@
 // Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
 // Returns: basic_string_view(data()+pos, rlen).
 
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <stdexcept>
-#include <string_view>
+#if 0
+#  include <algorithm>
+#  include <cassert>
+#  include <string_view>
 
-#include "test_macros.h"
+#  include "make_string.h"
+#  include "test_macros.h"
+
+#  define CS(S) MAKE_CSTRING(CharT, S)
 
 template <typename CharT>
 struct Test {
   typedef std::basic_string_view<CharT> (std::basic_string_view<CharT>::*Sub)(
-      typename std::basic_string_view<CharT>::size_type, typename std::basic_string_view<CharT>::size_type) const;
+      typename std::basic_string_view<CharT>::size_type = 0, typename std::basic_string_view<CharT>::size_type = npos) const;
 };
 
+
 template <typename CharT, typename Test<CharT>::Sub TestSub>
-void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
+TEST_CONSTEXPR_CXX14 void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
   std::basic_string_view<CharT> sv1;
-#ifdef TEST_HAS_NO_EXCEPTIONS
+#  ifdef TEST_HAS_NO_EXCEPTIONS
   if (pos > sv.size())
     return; // would throw if exceptions were enabled
   sv1 = (sv.*TestSub)(pos, n);
-#else
-  try {
-    sv1 = (sv.*TestSub)(pos, n);
-    assert(pos <= sv.size());
-  } catch (const std::out_of_range&) {
-    assert(pos > sv.size());
-    return;
+#  else
+  if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      sv1 = (sv.*TestSub)(pos, n);
+      assert(pos <= sv.size());
+    } catch (const std::out_of_range&) {
+      assert(pos > sv.size());
+      return;
+    }
   }
-#endif
+#  endif
   const std::size_t rlen = std::min(n, sv.size() - pos);
   assert(sv1.size() == rlen);
   for (std::size_t i = 0; i < rlen; ++i)
@@ -57,7 +62,7 @@ void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
 }
 
 template <typename CharT, typename Test<CharT>::Sub TestSub>
-void testCases(const CharT* s) {
+TEST_CONSTEXPR_CXX14 void testCases(const CharT* s) {
   std::basic_string_view<CharT> sv(s);
 
   testDetail<CharT, TestSub>(sv, 0, 0);
@@ -71,87 +76,157 @@ void testCases(const CharT* s) {
   testDetail<CharT, TestSub>(sv, 2, std::basic_string_view<CharT>::npos);
   testDetail<CharT, TestSub>(sv, sv.size(), std::basic_string_view<CharT>::npos);
 
+  // Test if exceptions are thrown correctly.
   testDetail<CharT, TestSub>(sv, sv.size() + 1, 0);
   testDetail<CharT, TestSub>(sv, sv.size() + 1, 1);
   testDetail<CharT, TestSub>(sv, sv.size() + 1, std::basic_string_view<CharT>::npos);
 }
 
 template <typename CharT>
-void testSubs(const CharT* s) {
+TEST_CONSTEXPR_CXX14 void testSubs(const CharT* s) {
   testCases<CharT, &std::basic_string_view<CharT>::substr>(s);
-#if TEST_STD_VER >= 26
+#  if TEST_STD_VER >= 26
   testCases<CharT, &std::basic_string_view<CharT>::subview>(s);
-#endif
+#  endif
 }
 
-void test() {
-  testSubs("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  testSubs("ABCDE");
-  testSubs("a");
-  testSubs("");
+#  define CS(S) MAKE_CSTRING(CharT, S)
 
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+template <typename CharT>
+TEST_CONSTEXPR_CXX14 void test() {
   testSubs(
-      L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  testSubs(L"ABCDE");
-  testSubs(L"a");
-  testSubs(L"");
-#endif
+      CS("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE"));
+  testSubs(CS("ABCDE"));
+  testSubs(CS("a"));
+  testSubs(CS(""));
+}
 
-#if TEST_STD_VER >= 11
-  testSubs(
-      u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  testSubs(u"ABCDE");
-  testSubs(u"a");
-  testSubs(u"");
+TEST_CONSTEXPR_CXX14 bool test() {
+  test<char>();
+#  ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#  endif
+#  if TEST_STD_VER >= 11
+#    ifndef TEST_HAS_NO_CHAR8_T
+  test<char8_t>();
+#    endif
+  test<char16_t>();
+  test<char32_t>();
+#  endif
 
-  testSubs(
-      U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
-  testSubs(U"ABCDE");
-  testSubs(U"a");
-  testSubs(U"");
-#endif
+  return true;
 }
 
-#if TEST_STD_VER >= 14
-template <typename Test<char>::Sub TestSub>
-constexpr void testConstexprDetail() {
-  constexpr std::string_view sv{"ABCDE", 5};
-  {
-    constexpr std::string_view sv2 = (sv.*TestSub)(0, 3);
-
-    static_assert(sv2.size() == 3, "");
-    static_assert(sv2[0] == 'A', "");
-    static_assert(sv2[1] == 'B', "");
-    static_assert(sv2[2] == 'C', "");
-  }
+int main(int, char**) {
+  test();
+#  if TEST_STD_VER >= 14
+  // static_assert(test());
+#  endif
 
-  {
-    constexpr std::string_view sv2 = (sv.*TestSub)(3, 0);
-    static_assert(sv2.size() == 0, "");
-  }
+  return 0;
+}
+#endif
+
+#include <cassert>
+#include <string>
+#include <utility>
+
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "test_macros.h"
+
+#define CS(S) MAKE_CSTRING(CharT, S)
+
+template <typename CharT, typename TraitsT>
+struct Test {
+  typedef std::basic_string_view<CharT, TraitsT> (std::basic_string_view<CharT, TraitsT>::*Sub)(
+      typename std::basic_string_view<CharT, TraitsT>::size_type,
+      typename std::basic_string_view<CharT, TraitsT>::size_type) const;
+};
 
-  {
-    constexpr std::string_view sv2 = (sv.*TestSub)(3, 3);
-    static_assert(sv2.size() == 2, "");
-    static_assert(sv2[0] == 'D', "");
-    static_assert(sv2[1] == 'E', "");
+template <typename CharT, typename TraitsT, typename Test<CharT, TraitsT>::Sub TestSub>
+TEST_CONSTEXPR_CXX14 void test() {
+  const std::basic_string_view<CharT, TraitsT> sv = CS("Hello cruel world!");
+
+  // With a default position and a character length.
+  assert((sv.*TestSub)(0, std::basic_string_view<CharT, TraitsT>::npos) == CS("Hello cruel world!"));
+
+  // With a explict position and a character length.
+  assert((sv.*TestSub)(6, 5) == CS("cruel"));
+
+  // From the beginning of the string with a explicit character length.
+  assert((sv.*TestSub)(0, 5) == CS("Hello"));
+
+  // To the end of string with the default character length.
+  assert((sv.*TestSub)(12, std::basic_string_view<CharT, TraitsT>::npos) == CS("world!"));
+
+  // From the beginning to the end of the string with explicit values.
+  assert((sv.*TestSub)(0, sv.size()) == CS("Hello cruel world!"));
+
+  // Test if exceptions are thrown correctly.
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  if (!TEST_IS_CONSTANT_EVALUATED) {
+    { // With a position that is out of range.
+      try {
+        (sv.*TestSub)(sv.size() + 1, std::basic_string_view<CharT, TraitsT>::npos);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
+
+    { // With a position that is out of range and a 0 character length.
+      try {
+        (sv.*TestSub)(sv.size() + 1, 0);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
+
+    { // With a position that is out of range and a some character length.
+      try {
+        (sv.*TestSub)(sv.size() + 1, 1);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception
+      }
+    }
   }
+#endif
 }
 
-void test_constexpr() {
-  testConstexprDetail<&std::string_view::substr>();
-#  if TEST_STD_VER >= 26
-  testConstexprDetail<&std::string_view::subview>();
-#  endif
+template <typename CharT>
+TEST_CONSTEXPR_CXX14 void test() {
+  ASSERT_SAME_TYPE(std::basic_string_view<CharT>, decltype(std::declval<std::basic_string_view<CharT> >().substr()));
+  test<CharT, std::char_traits<CharT>, &std::basic_string_view<CharT, std::char_traits<CharT> >::substr>();
+  test<CharT, constexpr_char_traits<CharT>, &std::basic_string_view<CharT, constexpr_char_traits<CharT> >::substr>();
+#if TEST_STD_VER >= 26
+  ASSERT_SAME_TYPE(std::basic_string_view<CharT>, decltype(std::declval<std::basic_string_view<CharT> >().subview()));
+  test<CharT, std::char_traits<CharT>, &std::basic_string_view<CharT, std::char_traits<CharT>>::subview>();
+  test<CharT, constexpr_char_traits<CharT>, &std::basic_string_view<CharT, constexpr_char_traits<CharT> >::subview>();
+#endif
 }
+
+TEST_CONSTEXPR_CXX14 bool test() {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+  test<char8_t>();
 #endif
+  test<char16_t>();
+  test<char32_t>();
+
+  return true;
+}
 
 int main(int, char**) {
   test();
 #if TEST_STD_VER >= 14
-  test_constexpr();
+  static_assert(test());
 #endif
 
   return 0;
-}
+}
\ No newline at end of file

>From 14827405227f450e0bc0b6d69b8419254afec175 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 09:07:06 +0300
Subject: [PATCH 08/13] Addressed comments

---
 .../string.ops/string_substr/subview.pass.cpp |  12 +-
 .../string.view.ops/substr.pass.cpp           | 249 +++++-------------
 .../string.view.ops/subview.pass.cpp          | 104 +++++++-
 3 files changed, 179 insertions(+), 186 deletions(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index ab74624ccb393..8d714fff8cd3b 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -30,12 +30,12 @@ constexpr void test() {
 
   { // With a default position and a character length.
 
+    // Also check if subview() is a const-qualified.
+    assert(std::as_const(s).subview() == CS("Hello cruel world!"));
+
     // Check it the return type of subview() is correct.
     std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview();
-
     assert(sv == CS("Hello cruel world!"));
-    // Also check if subview() is a const-qualified.
-    assert(std::as_const(s).subview() == CS("Hello cruel world!"));
   }
 
   { // Check with different position and length.
@@ -44,13 +44,13 @@ constexpr void test() {
     assert(s.subview(6, 5) == CS("cruel"));
 
     // From the beginning of the string with a explicit character length.
-    assert(sv = s.subview(0, 5) == CS("Hello"));
+    assert(s.subview(0, 5) == CS("Hello"));
 
     // To the end of string with the default character length.
-    assert(subview(12) == CS("world!"));
+    assert(s.subview(12) == CS("world!"));
 
     // From the beginning to the end of the string with explicit values.
-    assert(subview(0, s.size() == CS("Hello cruel world!"));
+    assert(s.subview(0, s.size()) == CS("Hello cruel world!"));
   }
 
   // Test if exceptions are thrown correctly.
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
index 6ed46452365a5..62b0259c175f8 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
@@ -11,222 +11,115 @@
 // <string_view>
 
 // constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
-// constexpr basic_string_view subview(size_type pos = 0,
-//                                     size_type n = npos) const;      // freestanding-deleted
-
-// subview is alternative name of substr
 
 // Throws: out_of_range if pos > size().
 // Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
 // Returns: basic_string_view(data()+pos, rlen).
 
-#if 0
-#  include <algorithm>
-#  include <cassert>
-#  include <string_view>
-
-#  include "make_string.h"
-#  include "test_macros.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <stdexcept>
+#include <string_view>
 
-#  define CS(S) MAKE_CSTRING(CharT, S)
+#include "test_macros.h"
 
 template <typename CharT>
-struct Test {
-  typedef std::basic_string_view<CharT> (std::basic_string_view<CharT>::*Sub)(
-      typename std::basic_string_view<CharT>::size_type = 0, typename std::basic_string_view<CharT>::size_type = npos) const;
-};
-
-
-template <typename CharT, typename Test<CharT>::Sub TestSub>
-TEST_CONSTEXPR_CXX14 void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
+void test1(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
   std::basic_string_view<CharT> sv1;
-#  ifdef TEST_HAS_NO_EXCEPTIONS
+#ifdef TEST_HAS_NO_EXCEPTIONS
   if (pos > sv.size())
     return; // would throw if exceptions were enabled
-  sv1 = (sv.*TestSub)(pos, n);
-#  else
-  if (!TEST_IS_CONSTANT_EVALUATED) {
-    try {
-      sv1 = (sv.*TestSub)(pos, n);
-      assert(pos <= sv.size());
-    } catch (const std::out_of_range&) {
-      assert(pos > sv.size());
-      return;
-    }
+  sv1 = sv.substr(pos, n);
+#else
+  try {
+    sv1 = sv.substr(pos, n);
+    assert(pos <= sv.size());
+  } catch (const std::out_of_range&) {
+    assert(pos > sv.size());
+    return;
   }
-#  endif
+#endif
   const std::size_t rlen = std::min(n, sv.size() - pos);
   assert(sv1.size() == rlen);
   for (std::size_t i = 0; i < rlen; ++i)
     assert(sv[pos + i] == sv1[i]);
 }
 
-template <typename CharT, typename Test<CharT>::Sub TestSub>
-TEST_CONSTEXPR_CXX14 void testCases(const CharT* s) {
-  std::basic_string_view<CharT> sv(s);
+template <typename CharT>
+void test(const CharT* s) {
+  typedef std::basic_string_view<CharT> string_view_t;
 
-  testDetail<CharT, TestSub>(sv, 0, 0);
-  testDetail<CharT, TestSub>(sv, 1, 0);
-  testDetail<CharT, TestSub>(sv, 20, 0);
-  testDetail<CharT, TestSub>(sv, sv.size(), 0);
+  string_view_t sv1(s);
 
-  testDetail<CharT, TestSub>(sv, 100, 3);
+  test1(sv1, 0, 0);
+  test1(sv1, 1, 0);
+  test1(sv1, 20, 0);
+  test1(sv1, sv1.size(), 0);
 
-  testDetail<CharT, TestSub>(sv, 0, std::basic_string_view<CharT>::npos);
-  testDetail<CharT, TestSub>(sv, 2, std::basic_string_view<CharT>::npos);
-  testDetail<CharT, TestSub>(sv, sv.size(), std::basic_string_view<CharT>::npos);
+  test1(sv1, 0, 3);
+  test1(sv1, 2, 3);
+  test1(sv1, 100, 3);
 
-  // Test if exceptions are thrown correctly.
-  testDetail<CharT, TestSub>(sv, sv.size() + 1, 0);
-  testDetail<CharT, TestSub>(sv, sv.size() + 1, 1);
-  testDetail<CharT, TestSub>(sv, sv.size() + 1, std::basic_string_view<CharT>::npos);
-}
+  test1(sv1, 0, string_view_t::npos);
+  test1(sv1, 2, string_view_t::npos);
+  test1(sv1, sv1.size(), string_view_t::npos);
 
-template <typename CharT>
-TEST_CONSTEXPR_CXX14 void testSubs(const CharT* s) {
-  testCases<CharT, &std::basic_string_view<CharT>::substr>(s);
-#  if TEST_STD_VER >= 26
-  testCases<CharT, &std::basic_string_view<CharT>::subview>(s);
-#  endif
-}
-
-#  define CS(S) MAKE_CSTRING(CharT, S)
-
-template <typename CharT>
-TEST_CONSTEXPR_CXX14 void test() {
-  testSubs(
-      CS("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE"));
-  testSubs(CS("ABCDE"));
-  testSubs(CS("a"));
-  testSubs(CS(""));
-}
-
-TEST_CONSTEXPR_CXX14 bool test() {
-  test<char>();
-#  ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#  endif
-#  if TEST_STD_VER >= 11
-#    ifndef TEST_HAS_NO_CHAR8_T
-  test<char8_t>();
-#    endif
-  test<char16_t>();
-  test<char32_t>();
-#  endif
-
-  return true;
+  test1(sv1, sv1.size() + 1, 0);
+  test1(sv1, sv1.size() + 1, 1);
+  test1(sv1, sv1.size() + 1, string_view_t::npos);
 }
 
 int main(int, char**) {
-  test();
-#  if TEST_STD_VER >= 14
-  // static_assert(test());
-#  endif
+  test("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  test("ABCDE");
+  test("a");
+  test("");
 
-  return 0;
-}
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test(L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  test(L"ABCDE");
+  test(L"a");
+  test(L"");
 #endif
 
-#include <cassert>
-#include <string>
-#include <utility>
-
-#include "constexpr_char_traits.h"
-#include "make_string.h"
-#include "test_macros.h"
+#if TEST_STD_VER >= 11
+  test(u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  test(u"ABCDE");
+  test(u"a");
+  test(u"");
 
-#define CS(S) MAKE_CSTRING(CharT, S)
-
-template <typename CharT, typename TraitsT>
-struct Test {
-  typedef std::basic_string_view<CharT, TraitsT> (std::basic_string_view<CharT, TraitsT>::*Sub)(
-      typename std::basic_string_view<CharT, TraitsT>::size_type,
-      typename std::basic_string_view<CharT, TraitsT>::size_type) const;
-};
-
-template <typename CharT, typename TraitsT, typename Test<CharT, TraitsT>::Sub TestSub>
-TEST_CONSTEXPR_CXX14 void test() {
-  const std::basic_string_view<CharT, TraitsT> sv = CS("Hello cruel world!");
-
-  // With a default position and a character length.
-  assert((sv.*TestSub)(0, std::basic_string_view<CharT, TraitsT>::npos) == CS("Hello cruel world!"));
-
-  // With a explict position and a character length.
-  assert((sv.*TestSub)(6, 5) == CS("cruel"));
-
-  // From the beginning of the string with a explicit character length.
-  assert((sv.*TestSub)(0, 5) == CS("Hello"));
-
-  // To the end of string with the default character length.
-  assert((sv.*TestSub)(12, std::basic_string_view<CharT, TraitsT>::npos) == CS("world!"));
+  test(U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+  test(U"ABCDE");
+  test(U"a");
+  test(U"");
+#endif
 
-  // From the beginning to the end of the string with explicit values.
-  assert((sv.*TestSub)(0, sv.size()) == CS("Hello cruel world!"));
+#if TEST_STD_VER > 11
+  {
+    constexpr std::string_view sv1{"ABCDE", 5};
 
-  // Test if exceptions are thrown correctly.
-#ifndef TEST_HAS_NO_EXCEPTIONS
-  if (!TEST_IS_CONSTANT_EVALUATED) {
-    { // With a position that is out of range.
-      try {
-        (sv.*TestSub)(sv.size() + 1, std::basic_string_view<CharT, TraitsT>::npos);
-        assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception
-      }
+    {
+      constexpr std::string_view sv2 = sv1.substr(0, 3);
+      static_assert(sv2.size() == 3, "");
+      static_assert(sv2[0] == 'A', "");
+      static_assert(sv2[1] == 'B', "");
+      static_assert(sv2[2] == 'C', "");
     }
 
-    { // With a position that is out of range and a 0 character length.
-      try {
-        (sv.*TestSub)(sv.size() + 1, 0);
-        assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception
-      }
+    {
+      constexpr std::string_view sv2 = sv1.substr(3, 0);
+      static_assert(sv2.size() == 0, "");
     }
 
-    { // With a position that is out of range and a some character length.
-      try {
-        (sv.*TestSub)(sv.size() + 1, 1);
-        assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception
-      }
+    {
+      constexpr std::string_view sv2 = sv1.substr(3, 3);
+      static_assert(sv2.size() == 2, "");
+      static_assert(sv2[0] == 'D', "");
+      static_assert(sv2[1] == 'E', "");
     }
   }
 #endif
-}
-
-template <typename CharT>
-TEST_CONSTEXPR_CXX14 void test() {
-  ASSERT_SAME_TYPE(std::basic_string_view<CharT>, decltype(std::declval<std::basic_string_view<CharT> >().substr()));
-  test<CharT, std::char_traits<CharT>, &std::basic_string_view<CharT, std::char_traits<CharT> >::substr>();
-  test<CharT, constexpr_char_traits<CharT>, &std::basic_string_view<CharT, constexpr_char_traits<CharT> >::substr>();
-#if TEST_STD_VER >= 26
-  ASSERT_SAME_TYPE(std::basic_string_view<CharT>, decltype(std::declval<std::basic_string_view<CharT> >().subview()));
-  test<CharT, std::char_traits<CharT>, &std::basic_string_view<CharT, std::char_traits<CharT>>::subview>();
-  test<CharT, constexpr_char_traits<CharT>, &std::basic_string_view<CharT, constexpr_char_traits<CharT> >::subview>();
-#endif
-}
-
-TEST_CONSTEXPR_CXX14 bool test() {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-#ifndef TEST_HAS_NO_CHAR8_T
-  test<char8_t>();
-#endif
-  test<char16_t>();
-  test<char32_t>();
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-#if TEST_STD_VER >= 14
-  static_assert(test());
-#endif
 
   return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
index fec258eef4546..57947bd0e9ecd 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -13,8 +13,108 @@
 // constexpr basic_string_view subview(size_type pos = 0,
 //                                     size_type n = npos) const;      // freestanding-deleted
 
+#include <cassert>
+#include <string>
+#include <utility>
+
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "test_macros.h"
+
+#define CS(S) MAKE_CSTRING(CharT, S)
+
+template <typename CharT, typename TraitsT>
+constexpr void test() {
+  std::basic_string_view<CharT, TraitsT> sv{CS("Hello cruel world!")};
+
+  { // With a default position and a character length.
+
+    // Check if subview() is a const-qualified.
+    assert(std::as_const(sv).subview() == CS("Hello cruel world!"));
+
+    // Check if the return type of subview() is correct.
+    std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) subsv = sv.subview();
+    assert(subsv == CS("Hello cruel world!"));
+  }
+
+  { // Check with different position and length.
+
+    // With a explict position and a character length.
+    assert(sv.subview(6, 5) == CS("cruel"));
+
+    // From the beginning of the string with a explicit character length.
+    assert(sv.subview(0, 5) == CS("Hello"));
+
+    // To the end of string with the default character length.
+    assert(sv.subview(12) == CS("world!"));
+
+    // From the beginning to the end of the string with explicit values.
+    assert(sv.subview(0, sv.size()) == CS("Hello cruel world!"));
+  }
+
+  // Test if exceptions are thrown correctly.
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  if (!std::is_constant_evaluated()) {
+    { // With a position that is out of range.
+      try {
+        sv.subview(sv.size() + 1);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception...
+      }
+    }
+
+    { // With a position that is out of range and a 0 character length.
+      try {
+        sv.subview(sv.size() + 1, 0);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception...
+      }
+    }
+
+    { // With a position that is out of range and a some character length.
+      try {
+        sv.subview(sv.size() + 1, 1);
+        assert(false && "Expected std::out_of_range exception");
+      } catch (const std::out_of_range&) {
+        // Expected exception...
+      }
+    }
+  }
+#endif
+}
+
+template <typename CharT>
+constexpr void test() {
+  test<CharT, std::char_traits<CharT>>();
+  test<CharT, std::char_traits<CharT>>();
+  test<CharT, std::char_traits<CharT>>();
+  test<CharT, std::char_traits<CharT>>();
+
+  test<CharT, constexpr_char_traits<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>>();
+  test<CharT, constexpr_char_traits<CharT>>();
+}
+
+constexpr bool test() {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+  test<char16_t>();
+  test<char32_t>();
+
+  return true;
+}
+
 int main(int, char**) {
-  // This test is intentionally empty because subview is an alias for substr
-  // and is tested in substr.pass.cpp.
+  test();
+  static_assert(test());
+
   return 0;
 }

>From 568336fa15ff138f85a7de9ef4e4229d5820b90b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 17:20:12 +0300
Subject: [PATCH 09/13] Fix CI

---
 .../basic.string/string.ops/string_substr/subview.pass.cpp     | 2 ++
 .../std/strings/string.view/string.view.ops/subview.pass.cpp   | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 8d714fff8cd3b..09ff13f98b009 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -13,7 +13,9 @@
 // constexpr basic_string_view<_CharT, _Traits> subview(size_type __pos = 0, size_type __n = npos) const;
 
 #include <cassert>
+#include <concepts>
 #include <string>
+#include <string_view>
 #include <utility>
 
 #include "constexpr_char_traits.h"
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
index 57947bd0e9ecd..ee083a8d432ac 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -14,7 +14,8 @@
 //                                     size_type n = npos) const;      // freestanding-deleted
 
 #include <cassert>
-#include <string>
+#include <concepts>
+#include <string_view>
 #include <utility>
 
 #include "constexpr_char_traits.h"

>From fb19c8ab81594097d2cbabd592102540af867a8a Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 18:54:30 +0300
Subject: [PATCH 10/13] Updated implementation and tests

---
 libcxx/include/string_view                    |  7 +++++--
 .../string.ops/string_substr/subview.pass.cpp | 18 +++++++++++------
 .../string.view.ops/subview.pass.cpp          | 20 ++++++++++++-------
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 952d44123622b..7b093813b52c5 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -469,8 +469,11 @@ public:
 
 #  if _LIBCPP_STD_VER >= 26
   _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
-    return this->substr(__pos, __n);
-  }
+    // Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
+    // valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
+    // new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634.
+    return __pos > size() ? (__throw_out_of_range("string_view::subview"), basic_string_view())
+                          : basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));  }
 #  endif
 
   _LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
index 09ff13f98b009..7b9b0df9aad32 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -62,8 +62,10 @@ constexpr void test() {
       try {
         s.subview(s.size() + 1);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
 
@@ -71,8 +73,10 @@ constexpr void test() {
       try {
         s.subview(s.size() + 1, 0);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
 
@@ -80,8 +84,10 @@ constexpr void test() {
       try {
         s.subview(s.size() + 1, 1);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
   }
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
index ee083a8d432ac..a4d0467738041 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -60,8 +60,10 @@ constexpr void test() {
       try {
         sv.subview(sv.size() + 1);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
 
@@ -69,8 +71,10 @@ constexpr void test() {
       try {
         sv.subview(sv.size() + 1, 0);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
 
@@ -78,8 +82,10 @@ constexpr void test() {
       try {
         sv.subview(sv.size() + 1, 1);
         assert(false && "Expected std::out_of_range exception");
-      } catch (const std::out_of_range&) {
-        // Expected exception...
+      } catch ([[maybe_unused]] const std::out_of_range& ex) {
+        LIBCPP_ASSERT(std::string(ex.what()) == "string_view::subview");
+      } catch (...) {
+        assert(false && "Expected std::out_of_range exception");
       }
     }
   }
@@ -115,7 +121,7 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  static_assert(test());
+  // static_assert(test());
 
   return 0;
 }

>From 5f64a5ae872f48331906a9fec66364d81e97d895 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hristo.goshev.hristov at gmail.com>
Date: Wed, 6 Aug 2025 18:58:54 +0300
Subject: [PATCH 11/13] Update
 libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp

---
 .../std/strings/string.view/string.view.ops/subview.pass.cpp    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
index a4d0467738041..b135cce7aa2c4 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -121,7 +121,7 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  // static_assert(test());
+  static_assert(test());
 
   return 0;
 }

>From d3eeeb46484466342aa5588ae03ee13b4aae99eb Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 19:11:32 +0300
Subject: [PATCH 12/13] Update some more

---
 libcxx/include/string_view | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 7b093813b52c5..e38a7ce7c6a73 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -459,21 +459,23 @@ public:
     return __rlen;
   }
 
-  _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view substr(size_type __pos = 0, size_type __n = npos) const {
+  _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI inline basic_string_view
+  __subview(size_type __pos, size_type __n, const char* __msg) const {
     // Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
     // valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
     // new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634.
-    return __pos > size() ? (__throw_out_of_range("string_view::substr"), basic_string_view())
+    return __pos > size() ? (__throw_out_of_range(__msg), basic_string_view())
                           : basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
   }
 
+  _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view substr(size_type __pos = 0, size_type __n = npos) const {
+    return __subview(__pos, __n, "string_view::substr");
+  }
+
 #  if _LIBCPP_STD_VER >= 26
   _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
-    // Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
-    // valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
-    // new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634.
-    return __pos > size() ? (__throw_out_of_range("string_view::subview"), basic_string_view())
-                          : basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));  }
+    return __subview(__pos, __n, "string_view::subview");
+  }
 #  endif
 
   _LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {

>From 292cb6c9f3409926b0be99609f0096bfa222e019 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 6 Aug 2025 19:36:58 +0300
Subject: [PATCH 13/13] Fixed `<version>`

---
 libcxx/docs/FeatureTestMacroTable.rst             |  4 ++--
 libcxx/include/version                            |  2 +-
 .../string.version.compile.pass.cpp               | 15 ++++++---------
 .../string_view.version.compile.pass.cpp          | 15 ++++++---------
 .../version.version.compile.pass.cpp              | 15 ++++++---------
 .../generate_feature_test_macro_components.py     |  2 +-
 6 files changed, 22 insertions(+), 31 deletions(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 1e88c6c0bec47..0008232ae91d5 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -404,8 +404,6 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_string_resize_and_overwrite``                  ``202110L``
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_string_subview``                               ``202506L``
-    ---------------------------------------------------------- -----------------
     ``__cpp_lib_to_underlying``                                ``202102L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_tuple_like``                                   *unimplemented*
@@ -508,6 +506,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_sstream_from_string_view``                     ``202306L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_string_subview``                               ``202506L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_string_view``                                  ``202403L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_submdspan``                                    *unimplemented*
diff --git a/libcxx/include/version b/libcxx/include/version
index 8c5defa3ed8a9..f2fb9aef923ee 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -536,7 +536,6 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_stdatomic_h                          202011L
 # define __cpp_lib_string_contains                      202011L
 # define __cpp_lib_string_resize_and_overwrite          202110L
-# define __cpp_lib_string_subview                       202506L
 # define __cpp_lib_to_underlying                        202102L
 // # define __cpp_lib_tuple_like                           202207L
 # define __cpp_lib_unreachable                          202202L
@@ -601,6 +600,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_span_at                              202311L
 # define __cpp_lib_span_initializer_list                202311L
 # define __cpp_lib_sstream_from_string_view             202306L
+# define __cpp_lib_string_subview                       202506L
 # undef  __cpp_lib_string_view
 # define __cpp_lib_string_view                          202403L
 // # define __cpp_lib_submdspan                            202306L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
index c69c8ed59fb61..147854eead2cc 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
@@ -61,7 +61,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifdef __cpp_lib_string_udls
@@ -119,7 +119,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -186,7 +186,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -274,7 +274,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -370,11 +370,8 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
 #  endif
 
-#  ifndef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should be defined in c++23"
-#  endif
-#  if __cpp_lib_string_subview != 202506L
-#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
index ed13f392b1b7f..2c3716111102a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
@@ -41,7 +41,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifdef __cpp_lib_string_view
@@ -71,7 +71,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifdef __cpp_lib_string_view
@@ -101,7 +101,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_view
@@ -149,7 +149,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_view
@@ -199,11 +199,8 @@
 #    error "__cpp_lib_string_contains should have the value 202011L in c++23"
 #  endif
 
-#  ifndef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should be defined in c++23"
-#  endif
-#  if __cpp_lib_string_subview != 202506L
-#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_view
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 15048bb2b3253..3c21ed92cfc49 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
@@ -821,7 +821,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifdef __cpp_lib_string_udls
@@ -1780,7 +1780,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -2925,7 +2925,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -4343,7 +4343,7 @@
 #  endif
 
 #  ifdef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should not be defined before c++23"
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
@@ -5994,11 +5994,8 @@
 #    error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
 #  endif
 
-#  ifndef __cpp_lib_string_subview
-#    error "__cpp_lib_string_subview should be defined in c++23"
-#  endif
-#  if __cpp_lib_string_subview != 202506L
-#    error "__cpp_lib_string_subview should have the value 202506L in c++23"
+#  ifdef __cpp_lib_string_subview
+#    error "__cpp_lib_string_subview should not be defined before c++26"
 #  endif
 
 #  ifndef __cpp_lib_string_udls
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 6403743d20b7e..2c0c304d5c2f4 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1337,7 +1337,7 @@ def add_version_header(tc):
         },
         {
             "name": "__cpp_lib_string_subview",
-            "values": {"c++23": 202506},
+            "values": {"c++26": 202506},
             "headers": ["string", "string_view"],
         },
         {



More information about the libcxx-commits mailing list