{"id":2226104,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2226104/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.1@forge-stage.sourceware.org/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.2/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.1@forge-stage.sourceware.org>","list_archive_url":null,"date":"2026-04-22T09:01:30","name":"[v1,1/1] libstdc++: Add P1206R7 from_range members to std::vector [PR111055]","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"a249703a54442613684d3707087e79b9015c5ceb","submitter":{"id":93210,"url":"http://patchwork.ozlabs.org/api/1.2/people/93210/?format=json","name":"Jonathan Wakely via Sourceware Forge","email":"forge-bot+redi@forge-stage.sourceware.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.1@forge-stage.sourceware.org/mbox/","series":[{"id":500951,"url":"http://patchwork.ozlabs.org/api/1.2/series/500951/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=500951","date":"2026-04-22T09:01:29","name":"libstdc++: Add P1206R7 from_range members to std::vector [PR111055]","version":1,"mbox":"http://patchwork.ozlabs.org/series/500951/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2226104/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2226104/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org","sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org","server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0tct3V8Vz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 19:06:21 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8AB824B9DB7E\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 09:06:19 +0000 (GMT)","from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 1186B4B9DB7A\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 09:02:28 +0000 (GMT)","from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id D88CF40539\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 09:02:27 +0000 (UTC)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 8AB824B9DB7E","OpenDKIM Filter v2.11.0 sourceware.org 1186B4B9DB7A"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 1186B4B9DB7A","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 1186B4B9DB7A","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776848548; cv=none;\n b=Wajt/vs32E+5+VNsiOJqN6VfeYd9v3Lwm6vbpOecM0AHQiHlr+MrAiysu2tcxHENzMOw+N6OpEBgXO/hIeJKJNwk5iMVGg0ywyI1qZz1/qoLKHQo3qMQ1cNVcwTRFY2WFh6UFqtCj+ZJSczdcl1AkMKVXBxVzNv1vT34tKRmD+0=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776848548; c=relaxed/simple;\n bh=rcJf4vVvVYdY9tVrQvS2r3c92PTbnol6zkmQlvxxij0=;\n h=From:Date:Subject:To:Message-ID;\n b=S2JWy7/yrEmyVomJalu4ComqAtrDhUMqJmqEJXMGZXf37uGmitOnjr1PF+lo0umvK6ymFVAuRBQf7hNKFtAI65BEMOreY5MqmXL22XFeipITLX9IJA4j2Zd+3eFwKOaNdSZgo4xGIfiOreucQgGnPcF7xjSqmFg9Ygcm3etacSI=","ARC-Authentication-Results":"i=1; server2.sourceware.org","From":"Jonathan Wakely via Sourceware Forge\n <forge-bot+redi@forge-stage.sourceware.org>","Date":"Wed, 22 Apr 2026 09:01:30 +0000","Subject":"[PATCH v1 1/1] libstdc++: Add P1206R7 from_range members to\n std::vector [PR111055]","To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>","Message-ID":"\n <bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.1@forge-stage.sourceware.org>","X-Mailer":"batrachomyomachia","X-Requested-Reviewer":"ppalka","X-Pull-Request-Organization":"gcc","X-Pull-Request-Repository":"gcc-TEST","X-Pull-Request":"https://forge.sourceware.org/gcc/gcc-TEST/pulls/5","References":"\n <bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.0@forge-stage.sourceware.org>","In-Reply-To":"\n <bmm.hhu8xfp4me.gcc.gcc-TEST.redi.5.1.0@forge-stage.sourceware.org>","X-Patch-URL":"\n https://forge.sourceware.org/redi/gcc/commit/f53e3738a0f3b46f76d2c169a24fe65d3c862667","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Reply-To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>, redi@gcc.gnu.org","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":"From: Jonathan Wakely <jwakely@redhat.com>\n\nThis is another piece of P1206R7, adding new members to std::vector and\nstd::vector<bool>.\n\nThe new tests revealed a latent bug in std::vector<bool>::emplace_back,\nwhich this fixes.\n\nThe __uninitialized_copy_a extension needs to be enhanced to support\npassing non-common ranges (i.e. a sentinel that is a different type from\nthe iterator) and move-only input iterators.\n\nlibstdc++-v3/ChangeLog:\n\n\tPR libstdc++/111055\n\t* include/bits/ranges_base.h (__container_compatible_range): New\n\tconcept.\n\t* include/bits/stl_bvector.h (vector(from_range, R&&, const Alloc&))\n\t(assign_range, insert_range, append_range): Define.\n\t(emplace_back): Forward parameter pack.\n\t* include/bits/stl_uninitialized.h (__do_uninit_copy): Support\n\tnon-common ranges.\n\t(__uninitialized_copy_a): Likewise.\n\t* include/bits/stl_vector.h (_Vector_base::_M_append_range_to):\n\tNew function.\n\t(_Vector_base::_M_append_range): Likewise.\n\t(vector(from_range, R&&, const Alloc&), assign_range): Define.\n\t(append_range): Define.\n\t(insert_range): Declare.\n\t* include/debug/vector (vector(from_range, R&&, const Alloc&))\n\t(assign_range, insert_range, append_range): Define.\n\t* include/bits/vector.tcc (insert_range): Define.\n\t* testsuite/util/testsuite_iterators.h (input_iterator_wrapper_rval):\n\tNew class template.\n\t* testsuite/23_containers/vector/bool/cons/from_range.cc: New test.\n\t* testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:\n\tNew test.\n\t* testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:\n\tNew test.\n\t* testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:\n\tNew test.\n\t* testsuite/23_containers/vector/cons/from_range.cc: New test.\n\t* testsuite/23_containers/vector/modifiers/append_range.cc: New test.\n\t* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:\n\tNew test.\n\t* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:\n\tNew test.\n---\n libstdc++-v3/include/bits/ranges_base.h       |  10 ++\n libstdc++-v3/include/bits/stl_bvector.h       | 122 ++++++++++++-\n libstdc++-v3/include/bits/stl_uninitialized.h |  37 +++-\n libstdc++-v3/include/bits/stl_vector.h        | 166 ++++++++++++++++++\n libstdc++-v3/include/bits/vector.tcc          | 123 +++++++++++++\n libstdc++-v3/include/debug/vector             |  70 ++++++++\n .../vector/bool/cons/from_range.cc            |  91 ++++++++++\n .../bool/modifiers/assign/assign_range.cc     | 106 +++++++++++\n .../bool/modifiers/insert/append_range.cc     |  93 ++++++++++\n .../bool/modifiers/insert/insert_range.cc     | 104 +++++++++++\n .../23_containers/vector/cons/from_range.cc   | 108 ++++++++++++\n .../vector/modifiers/append_range.cc          |  97 ++++++++++\n .../vector/modifiers/assign/assign_range.cc   | 121 +++++++++++++\n .../vector/modifiers/insert/insert_range.cc   | 108 ++++++++++++\n .../testsuite/util/testsuite_iterators.h      |  20 +++\n 15 files changed, 1367 insertions(+), 9 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc","diff":"diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h\nindex cb2eba1f841a..a2c743ff56bc 100644\n--- a/libstdc++-v3/include/bits/ranges_base.h\n+++ b/libstdc++-v3/include/bits/ranges_base.h\n@@ -1079,6 +1079,16 @@ namespace ranges\n #if __glibcxx_ranges_to_container // C++ >= 23\n   struct from_range_t { explicit from_range_t() = default; };\n   inline constexpr from_range_t from_range{};\n+\n+/// @cond undocumented\n+namespace __detail\n+{\n+  template<typename _Rg, typename _Tp>\n+    concept __container_compatible_range\n+      = ranges::input_range<_Rg>\n+\t  && convertible_to<ranges::range_reference_t<_Rg>, _Tp>;\n+}\n+/// @endcond\n #endif\n \n _GLIBCXX_END_NAMESPACE_VERSION\ndiff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h\nindex 42261ac5915f..8cf91f26dca7 100644\n--- a/libstdc++-v3/include/bits/stl_bvector.h\n+++ b/libstdc++-v3/include/bits/stl_bvector.h\n@@ -892,6 +892,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Construct a vector from a range.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<bool> _Rg>\n+\tconstexpr\n+\tvector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())\n+\t: _Base(__a)\n+\t{\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      _M_initialize(size_type(ranges::distance(__rg)));\n+\t      ranges::copy(__rg, begin());\n+\t    }\n+\t  else\n+\t    {\n+\t      auto __first = ranges::begin(__rg);\n+\t      const auto __last = ranges::end(__rg);\n+\t      for (; __first != __last; ++__first)\n+\t\templace_back(*__first);\n+\t    }\n+\t}\n+#endif\n+\n       _GLIBCXX20_CONSTEXPR\n       ~vector() _GLIBCXX_NOEXCEPT { }\n \n@@ -996,6 +1021,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); }\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Assign a range to the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<bool> _Rg>\n+\tconstexpr void\n+\tassign_range(_Rg&& __rg)\n+\t{\n+\t  static_assert(assignable_from<bool&, ranges::range_reference_t<_Rg>>);\n+\t  clear();\n+\t  append_range(std::forward<_Rg>(__rg));\n+\t}\n+#endif\n+\n       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR\n       iterator\n       begin() _GLIBCXX_NOEXCEPT\n@@ -1279,6 +1319,86 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       { return this->insert(__p, __l.begin(), __l.end()); }\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Insert a range into the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<bool> _Rg>\n+\tconstexpr iterator\n+\tinsert_range(const_iterator __pos, _Rg&& __rg)\n+\t{\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      if (auto __n = size_type(ranges::distance(__rg)))\n+\t\t{\n+\t\t  if (capacity() - size() >= __n)\n+\t\t    {\n+\t\t      std::copy_backward(__pos._M_const_cast(), end(),\n+\t\t\t\t\t this->_M_impl._M_finish\n+\t\t\t\t\t   + difference_type(__n));\n+\t\t      auto __i = ranges::copy(__rg, __pos._M_const_cast()).out;\n+\t\t      this->_M_impl._M_finish += difference_type(__n);\n+\t\t      return __i;\n+\t\t    }\n+\t\t  else\n+\t\t    {\n+\t\t      const size_type __len =\n+\t\t\t_M_check_len(__n, \"vector<bool>::insert_range\");\n+\t\t      const iterator __begin = begin(), __end = end();\n+\t\t      _Bit_pointer __q = this->_M_allocate(__len);\n+\t\t      iterator __start(std::__addressof(*__q), 0);\n+\t\t      iterator __i = _M_copy_aligned(__begin,\n+\t\t\t\t\t\t     __pos._M_const_cast(),\n+\t\t\t\t\t\t     __start);\n+\t\t      __i = ranges::copy(__rg, __i).out;\n+\t\t      iterator __finish = std::copy(__pos._M_const_cast(),\n+\t\t\t\t\t\t    __end, __i);\n+\t\t      this->_M_deallocate();\n+\t\t      this->_M_impl._M_end_of_storage = __q + _S_nword(__len);\n+\t\t      this->_M_impl._M_start = __start;\n+\t\t      this->_M_impl._M_finish = __finish;\n+\t\t      return __i;\n+\t\t    }\n+\t\t}\n+\t      else\n+\t\treturn __pos._M_const_cast();\n+\t    }\n+\t  else\n+\t    return insert_range(__pos,\n+\t\t\t\tvector(from_range, __rg, get_allocator()));\n+\t}\n+\n+      /**\n+       * @brief Append a range at the end of the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<bool> _Rg>\n+\tconstexpr void\n+\tappend_range(_Rg&& __rg)\n+\t{\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      reserve(size() + size_type(ranges::distance(__rg)));\n+\t      this->_M_impl._M_finish = ranges::copy(__rg, end()).out;\n+\t    }\n+\t  else\n+\t    {\n+\t      auto __first = ranges::begin(__rg);\n+\t      const auto __last = ranges::end(__rg);\n+\t      size_type __n = size();\n+\t      const size_type __cap = capacity();\n+\t      for (; __first != __last && __n < __cap; ++__first, (void)++__n)\n+\t\templace_back(*__first);\n+\t      if (__first != __last)\n+\t\t{\n+\t\t  ranges::subrange __rest(std::move(__first), __last);\n+\t\t  append_range(vector(from_range, __rest, get_allocator()));\n+\t\t}\n+\t    }\n+\t}\n+#endif // ranges_to_container\n+\n       _GLIBCXX20_CONSTEXPR\n       void\n       pop_back()\n@@ -1343,7 +1463,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n #endif\n \templace_back(_Args&&... __args)\n \t{\n-\t  push_back(bool(__args...));\n+\t  push_back(bool(std::forward<_Args>(__args)...));\n #if __cplusplus > 201402L\n \t  return back();\n #endif\ndiff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h\nindex de3e8cbeaf58..2190261134e0 100644\n--- a/libstdc++-v3/include/bits/stl_uninitialized.h\n+++ b/libstdc++-v3/include/bits/stl_uninitialized.h\n@@ -132,10 +132,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     };\n \n   // This is the default implementation of std::uninitialized_copy.\n-  template<typename _InputIterator, typename _ForwardIterator>\n+  // This can be used with C++20 iterators and non-common ranges.\n+  template<typename _InputIterator, typename _Sentinel,\n+\t   typename _ForwardIterator>\n     _GLIBCXX20_CONSTEXPR\n     _ForwardIterator\n-    __do_uninit_copy(_InputIterator __first, _InputIterator __last,\n+    __do_uninit_copy(_InputIterator __first, _Sentinel __last,\n \t\t     _ForwardIterator __result)\n     {\n       _UninitDestroyGuard<_ForwardIterator> __guard(__result);\n@@ -568,11 +570,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n   //  default allocator.  For nondefault allocators we do not use\n   //  any of the POD optimizations.\n \n-  template<typename _InputIterator, typename _ForwardIterator,\n-\t   typename _Allocator>\n+  template<typename _InputIterator, typename _Sentinel,\n+\t   typename _ForwardIterator, typename _Allocator>\n     _GLIBCXX20_CONSTEXPR\n     _ForwardIterator\n-    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,\n+    __uninitialized_copy_a(_InputIterator __first, _Sentinel __last,\n \t\t\t   _ForwardIterator __result, _Allocator& __alloc)\n     {\n       _UninitDestroyGuard<_ForwardIterator, _Allocator>\n@@ -586,17 +588,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     }\n \n #if _GLIBCXX_HOSTED\n-  template<typename _InputIterator, typename _ForwardIterator, typename _Tp>\n+  template<typename _InputIterator, typename _Sentinel,\n+\t   typename _ForwardIterator, typename _Tp>\n     _GLIBCXX20_CONSTEXPR\n     inline _ForwardIterator\n-    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,\n+    __uninitialized_copy_a(_InputIterator __first, _Sentinel __last,\n \t\t\t   _ForwardIterator __result, allocator<_Tp>&)\n     {\n #ifdef __cpp_lib_is_constant_evaluated\n       if (std::is_constant_evaluated())\n-\treturn std::__do_uninit_copy(__first, __last, __result);\n+\treturn std::__do_uninit_copy(std::move(__first), __last, __result);\n #endif\n+\n+#ifdef __glibcxx_ranges\n+      if constexpr (!is_same_v<_InputIterator, _Sentinel>)\n+\t{\n+\t  // Convert to a common range if possible, to benefit from memcpy\n+\t  // optimizations that std::uninitialized_copy might use.\n+\t  if constexpr (sized_sentinel_for<_Sentinel, _InputIterator>\n+\t\t\t  && random_access_iterator<_InputIterator>)\n+\t    return std::uninitialized_copy(__first,\n+\t\t\t\t\t   __first + (__last - __first),\n+\t\t\t\t\t   __result);\n+\t  else // Just use default implementation.\n+\t    return std::__do_uninit_copy(std::move(__first), __last, __result);\n+\t}\n+      else\n+\treturn std::uninitialized_copy(std::move(__first), __last, __result);\n+#else\n       return std::uninitialized_copy(__first, __last, __result);\n+#endif\n     }\n #endif\n \ndiff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h\nindex 8982ca2b9eee..df48ba3377fa 100644\n--- a/libstdc++-v3/include/bits/stl_vector.h\n+++ b/libstdc++-v3/include/bits/stl_vector.h\n@@ -65,6 +65,10 @@\n #if __cplusplus >= 202002L\n # include <compare>\n #endif\n+#if __cplusplus > 202002L\n+# include <bits/ranges_algobase.h>      // ranges::copy\n+# include <bits/ranges_util.h>          // ranges::subrange\n+#endif\n \n #include <debug/assertions.h>\n \n@@ -399,6 +403,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \tthis->_M_impl._M_finish = this->_M_impl._M_start;\n \tthis->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;\n       }\n+\n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      // Called by insert_range, and indirectly by assign_range, append_range.\n+      // Initializes new elements in storage at __ptr and updates __ptr to\n+      // point after the last new element.\n+      // Provides strong exception safety guarantee.\n+      // Requires [ptr, ptr+distance(rg)) is a valid range.\n+      template<ranges::input_range _Rg>\n+\tconstexpr void\n+\t_M_append_range_to(_Rg&& __rg, pointer& __ptr)\n+\t{\n+\t  __ptr = std::__uninitialized_copy_a(ranges::begin(__rg),\n+\t\t\t\t\t      ranges::end(__rg),\n+\t\t\t\t\t      __ptr, _M_get_Tp_allocator());\n+\t}\n+\n+      // Called by assign_range, append_range, insert_range.\n+      // Requires capacity() >= size()+distance(rg).\n+      template<ranges::input_range _Rg>\n+\tconstexpr void\n+\t_M_append_range(_Rg&& __rg)\n+\t{ _M_append_range_to(std::forward<_Rg>(__rg), _M_impl._M_finish); }\n+#endif\n     };\n \n   /**\n@@ -723,6 +750,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Construct a vector from a range.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr\n+\tvector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())\n+\t: _Base(__a)\n+\t{\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      const auto __n = size_type(ranges::distance(__rg));\n+\t      pointer __start =\n+\t\tthis->_M_allocate(_S_check_init_len(__n,\n+\t\t\t\t\t\t    _M_get_Tp_allocator()));\n+\t      _Guard_alloc __guard(__start, __n, *this);\n+\t      this->_M_impl._M_finish = this->_M_impl._M_start = __start;\n+\t      this->_M_impl._M_end_of_storage = __start + __n;\n+\t      _Base::_M_append_range(__rg);\n+\t      (void) __guard._M_release();\n+\t    }\n+\t  else\n+\t    {\n+\t      // If an exception is thrown ~_Base() will deallocate storage,\n+\t      // but will not destroy elements. This RAII type destroys them.\n+\t      struct _Clear\n+\t      {\n+\t\t~_Clear() { if (_M_this) _M_this->clear(); }\n+\t\tvector* _M_this;\n+\t      } __guard{this};\n+\n+\t      auto __first = ranges::begin(__rg);\n+\t      const auto __last = ranges::end(__rg);\n+\t      for (; __first != __last; ++__first)\n+\t\templace_back(*__first);\n+\t      __guard._M_this = nullptr;\n+\t    }\n+\t}\n+#endif\n+\n       /**\n        *  The dtor only erases the elements, and note that if the\n        *  elements themselves are pointers, the pointed-to memory is\n@@ -859,6 +927,62 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n       }\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Assign a range to the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr void\n+\tassign_range(_Rg&& __rg)\n+\t{\n+\t  static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);\n+\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      const auto __n = size_type(ranges::distance(__rg));\n+\t      if (__n <= size())\n+\t\t{\n+\t\t  auto __res = ranges::copy(__rg, this->_M_impl._M_start);\n+\t\t  _M_erase_at_end(__res.out);\n+\t\t  return;\n+\t\t}\n+\n+\t      reserve(__n);\n+\t      auto __first = ranges::copy_n(ranges::begin(__rg), size(),\n+\t\t\t\t\t    this->_M_impl._M_start).in;\n+\t      [[maybe_unused]] const auto __diff = __n - size();\n+\t      _GLIBCXX_ASAN_ANNOTATE_GROW(__diff);\n+\t      _Base::_M_append_range(ranges::subrange(std::move(__first),\n+\t\t\t\t\t\t      ranges::end(__rg)));\n+\t      _GLIBCXX_ASAN_ANNOTATE_GREW(__diff);\n+\t    }\n+\t  else // input_range<_Rg> && !sized_range<_Rg>\n+\t    {\n+\t      auto __first = ranges::begin(__rg);\n+\t      const auto __last = ranges::end(__rg);\n+\t      pointer __ptr = this->_M_impl._M_start;\n+\t      pointer const __end = this->_M_impl._M_finish;\n+\n+\t      while (__ptr < __end && __first != __last)\n+\t\t{\n+\t\t  *__ptr = *__first;\n+\t\t  ++__ptr;\n+\t\t  ++__first;\n+\t\t}\n+\n+\t      if (__first == __last)\n+\t\t_M_erase_at_end(__ptr);\n+\t      else\n+\t\t{\n+\t\t  do\n+\t\t    emplace_back(*__first);\n+\t\t  while (++__first != __last);\n+\t\t}\n+\t    }\n+\t}\n+#endif // ranges_to_container\n+\n       /// Get a copy of the memory allocation object.\n       using _Base::get_allocator;\n \n@@ -1515,6 +1639,41 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Insert a range into the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr iterator\n+\tinsert_range(const_iterator __pos, _Rg&& __rg);\n+\n+      /**\n+       * @brief Append a range at the end of the vector.\n+       * @since C++23\n+       */\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr void\n+\tappend_range(_Rg&& __rg)\n+\t{\n+\t  if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)\n+\t    {\n+\t      const auto __n = size_type(ranges::distance(__rg));\n+\t      reserve(size() + __n);\n+\t      _GLIBCXX_ASAN_ANNOTATE_GROW(__n);\n+\t      _Base::_M_append_range(__rg);\n+\t      _GLIBCXX_ASAN_ANNOTATE_GREW(__n);\n+\t    }\n+\t  else\n+\t    {\n+\t      auto __first = ranges::begin(__rg);\n+\t      const auto __last = ranges::end(__rg);\n+\t      for (; __first != __last; ++__first)\n+\t\templace_back(*__first);\n+\t    }\n+\t}\n+#endif // ranges_to_container\n+\n       /**\n        *  @brief  Remove element at given position.\n        *  @param  __position  Iterator pointing to element to be erased.\n@@ -2049,6 +2208,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t   typename = _RequireAllocator<_Allocator>>\n     vector(_InputIterator, _InputIterator, _Allocator = _Allocator())\n       -> vector<_ValT, _Allocator>;\n+\n+#if __glibcxx_ranges_to_container // C++ >= 23\n+  template<ranges::input_range _Rg,\n+\t   typename _Alloc = allocator<ranges::range_value_t<_Rg>>>\n+    vector(from_range_t, _Rg&&, _Alloc = _Alloc())\n+      -> vector<ranges::range_value_t<_Rg>, _Alloc>;\n+#endif\n #endif\n \n   /**\ndiff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc\nindex a99a5b56b77a..542a66173a37 100644\n--- a/libstdc++-v3/include/bits/vector.tcc\n+++ b/libstdc++-v3/include/bits/vector.tcc\n@@ -974,6 +974,129 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t  }\n       }\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+  template<typename _Tp, typename _Alloc>\n+    template<__detail::__container_compatible_range<_Tp> _Rg>\n+      constexpr auto\n+      vector<_Tp, _Alloc>::\n+      insert_range(const_iterator __pos, _Rg&& __rg)\n+      -> iterator\n+      {\n+\tif (__pos == cend())\n+\t  {\n+\t    append_range(std::forward<_Rg>(__rg));\n+\t    return end();\n+\t  }\n+\n+\tif constexpr (ranges::forward_range<_Rg>)\n+\t  {\n+\t    // Start of existing elements:\n+\t    pointer __old_start = this->_M_impl._M_start;\n+\t    // End of existing elements:\n+\t    pointer __old_finish = this->_M_impl._M_finish;\n+\t    // Insertion point:\n+\t    const auto __ins_idx = __pos - cbegin();\n+\t    pointer __ins = __old_start + __ins_idx;\n+\t    // Number of new elements to insert:\n+\t    const auto __n = size_type(ranges::distance(__rg));\n+\t    // Number of elements that can fit in unused capacity:\n+\t    const auto __cap = this->_M_impl._M_end_of_storage - __old_finish;\n+\t    if (__cap >= __n)\n+\t      {\n+\t\t// Number of existing elements after insertion point:\n+\t\tconst size_type __elems_after = cend() - __pos;\n+\t\tif (__elems_after > __n)\n+\t\t  {\n+\t\t    _GLIBCXX_ASAN_ANNOTATE_GROW(__n);\n+\t\t    std::__uninitialized_move_a(__old_finish - __n,\n+\t\t\t\t\t\t__old_finish,\n+\t\t\t\t\t\t__old_finish,\n+\t\t\t\t\t\t_M_get_Tp_allocator());\n+\t\t    this->_M_impl._M_finish += __n;\n+\t\t    _GLIBCXX_ASAN_ANNOTATE_GREW(__n);\n+\t\t    std::move_backward(__ins, __old_finish - __n, __old_finish);\n+\t\t    ranges::copy(__rg, __ins);\n+\t\t  }\n+\t\telse\n+\t\t  {\n+\t\t    auto __first = ranges::begin(__rg);\n+\t\t    const auto __last = ranges::end(__rg);\n+\t\t    auto __mid = ranges::next(__first, __elems_after);\n+\t\t    _GLIBCXX_ASAN_ANNOTATE_GROW(__n);\n+\t\t    _Base::_M_append_range(ranges::subrange(__mid, __last));\n+\t\t    _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after);\n+\t\t    std::__uninitialized_move_a(__ins, __old_finish,\n+\t\t\t\t\t\tthis->_M_impl._M_finish,\n+\t\t\t\t\t\t_M_get_Tp_allocator());\n+\t\t    this->_M_impl._M_finish += __elems_after;\n+\t\t    _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after);\n+\t\t    ranges::copy(__first, __mid, __ins);\n+\t\t  }\n+\t      }\n+\t    else // Reallocate\n+\t      {\n+\t\tconst size_type __len\n+\t\t  = _M_check_len(__n, \"vector::insert_range\");\n+\n+\t\tstruct _Guard : _Guard_alloc\n+\t\t{\n+\t\t  // End of elements to destroy:\n+\t\t  pointer _M_finish = _Guard_alloc::_M_storage;\n+\n+\t\t  using _Guard_alloc::_Guard_alloc;\n+\n+\t\t  constexpr\n+\t\t  ~_Guard()\n+\t\t  {\n+\t\t    std::_Destroy(this->_M_storage, _M_finish,\n+\t\t\t\t  this->_M_vect._M_get_Tp_allocator());\n+\t\t  }\n+\t\t};\n+\n+\t\t// Allocate new storage:\n+\t\tpointer __new_start(this->_M_allocate(__len));\n+\t\t_Guard __guard(__new_start, __len, *this);\n+\n+\t\tauto& __alloc = _M_get_Tp_allocator();\n+\n+\t\t// Populate the new storage in three steps. After each step,\n+\t\t// __guard owns the new storage and any elements that have\n+\t\t// been constructed there.\n+\n+\t\t// Move elements from before insertion point to new storage:\n+\t\t__guard._M_finish\n+\t\t  = std::__uninitialized_move_if_noexcept_a(\n+\t\t      __old_start, __ins, __new_start, __alloc);\n+\n+\t\t// Append new elements to new storage:\n+\t\t_Base::_M_append_range_to(__rg, __guard._M_finish);\n+\n+\t\t// Move elements from after insertion point to new storage:\n+\t\t__guard._M_finish\n+\t\t    = std::__uninitialized_move_if_noexcept_a(\n+\t\t\t__ins, __old_finish, __guard._M_finish, __alloc);\n+\n+\t\t_GLIBCXX_ASAN_ANNOTATE_REINIT; // Creates _Asan::_Reinit.\n+\n+\t\t// All elements are in the new storage, exchange ownership\n+\t\t// with __guard so that it cleans up the old storage:\n+\t\tthis->_M_impl._M_start = __guard._M_storage;\n+\t\tthis->_M_impl._M_finish = __guard._M_finish;\n+\t\tthis->_M_impl._M_end_of_storage = __new_start + __len;\n+\t\t__guard._M_storage = __old_start;\n+\t\t__guard._M_finish = __old_finish;\n+\t\t__guard._M_len = (__old_finish - __old_start) + __cap;\n+\t\t// _Asan::_Reinit destructor marks unused capacity.\n+\t\t// _Guard destructor destroys [old_start,old_finish).\n+\t\t// _Guard_alloc destructor frees [old_start,old_start+len).\n+\t      }\n+\t    return begin() + __ins_idx;\n+\t  }\n+\telse\n+\t  return insert_range(__pos, vector(from_range, std::move(__rg),\n+\t\t\t\t\t    _M_get_Tp_allocator()));\n+      }\n+#endif // ranges_to_container\n \n   // vector<bool>\n   template<typename _Alloc>\ndiff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector\nindex fe43a372485d..f2ab4f737644 100644\n--- a/libstdc++-v3/include/debug/vector\n+++ b/libstdc++-v3/include/debug/vector\n@@ -244,6 +244,19 @@ namespace __debug\n \t     const allocator_type& __a = allocator_type())\n       : _Base(__l, __a) { }\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      /**\n+       * @brief Construct a vector from a range.\n+       * @since C++23\n+       */\n+      template<std::__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr\n+\tvector(std::from_range_t __t, _Rg&& __rg,\n+\t       const allocator_type& __a = allocator_type())\n+\t: _Base(__t, std::forward<_Rg>(__rg), __a)\n+\t{ }\n+#endif\n+\n       ~vector() = default;\n #endif\n \n@@ -858,6 +871,56 @@ namespace __debug\n       const _Base&\n       _M_base() const _GLIBCXX_NOEXCEPT { return *this; }\n \n+#if __glibcxx_ranges_to_container // C++ >= 23\n+      template<std::__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr void\n+\tassign_range(_Rg&& __rg)\n+\t{\n+\t  auto __old_begin = _Base::begin();\n+\t  auto __old_size = _Base::size();\n+\t  _Base::assign_range(__rg);\n+\t  if (!std::__is_constant_evaluated())\n+\t    {\n+\t      if (_Base::begin() != __old_begin)\n+\t\tthis->_M_invalidate_all();\n+\t      else if (_Base::size() < __old_size)\n+\t\tthis->_M_invalidate_after_nth(_Base::size());\n+\t      this->_M_update_guaranteed_capacity();\n+\t    }\n+\t}\n+\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr iterator\n+\tinsert_range(const_iterator __pos, _Rg&& __rg)\n+\t{\n+\t  auto __old_begin = _Base::begin();\n+\t  auto __old_size = _Base::size();\n+\t  auto __res = _Base::insert_range(__pos.base(), __rg);\n+\t  if (!std::__is_constant_evaluated())\n+\t    {\n+\t      if (_Base::begin() != __old_begin)\n+\t\tthis->_M_invalidate_all();\n+\t      this->_M_update_guaranteed_capacity();\n+\t    }\n+\t  return iterator(__res, this);\n+\t}\n+\n+      template<__detail::__container_compatible_range<_Tp> _Rg>\n+\tconstexpr void\n+\tappend_range(_Rg&& __rg)\n+\t{\n+\t  auto __old_begin = _Base::begin();\n+\t  auto __old_size = _Base::size();\n+\t  _Base::append_range(__rg);\n+\t  if (!std::__is_constant_evaluated())\n+\t    {\n+\t      if (_Base::begin() != __old_begin)\n+\t\tthis->_M_invalidate_all();\n+\t      this->_M_update_guaranteed_capacity();\n+\t    }\n+\t}\n+#endif\n+\n     private:\n       void\n       _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT\n@@ -937,6 +1000,13 @@ namespace __debug\n \t   typename = _RequireAllocator<_Allocator>>\n     vector(size_t, _Tp, _Allocator = _Allocator())\n       -> vector<_Tp, _Allocator>;\n+\n+#if __glibcxx_ranges_to_container // C++ >= 23\n+  template<ranges::input_range _Rg,\n+\t   typename _Alloc = allocator<ranges::range_value_t<_Rg>>>\n+    vector(from_range_t, _Rg&&, _Alloc = _Alloc())\n+      -> vector<ranges::range_value_t<_Rg>, _Alloc>;\n+#endif\n #endif\n \n } // namespace __debug\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc\nnew file mode 100644\nindex 000000000000..f5180e5a2433\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc\n@@ -0,0 +1,91 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test(Alloc alloc)\n+{\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,1,0,1,0,0,1,0,0};\n+\n+  auto eq = [](const std::vector<bool, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  std::vector<bool, Alloc> v0(std::from_range, Range(a, a+0));\n+  VERIFY( v0.empty() );\n+  VERIFY( v0.get_allocator() == Alloc() );\n+\n+  std::vector<bool, Alloc> v4(std::from_range, Range(a, a+4));\n+  VERIFY( eq(v4, {a, 4}) );\n+  VERIFY( v4.get_allocator() == Alloc() );\n+\n+  std::vector<bool, Alloc> v9(std::from_range, Range(a, a+9), alloc);\n+  VERIFY( eq(v9, {a, 9}) );\n+  VERIFY( v9.get_allocator() == alloc );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range>(std::allocator<bool>());\n+  do_test<Range>(__gnu_test::uneq_allocator<bool>(42));\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<bool>>();\n+  do_test_a<test_forward_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<bool>>();\n+  do_test_a<test_input_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(bool v) : val(v) { }\n+    operator bool() && { return val; }\n+    bool operator==(bool b) const { return b == val; }\n+    bool val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test_a<rvalue_input_range>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<bool>, std::allocator<bool>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc\nnew file mode 100644\nindex 000000000000..a014dfe90de7\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc\n@@ -0,0 +1,106 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,1,0,1,0,0,1,0,0};\n+\n+  auto eq = [](const std::vector<bool, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  Range r4(a, a+4);\n+  Range r9(a);\n+\n+  std::vector<bool, Alloc> v;\n+  v.assign_range(Range(a, a));\n+  VERIFY( v.empty() );\n+  VERIFY( v.capacity() == 0 );\n+  v.assign_range(r4);\n+  VERIFY( eq(v, {a, 4}) );\n+  v.clear();\n+  v.assign_range(r9); // larger than v.capacity()\n+  VERIFY( eq(v, a) );\n+  v.assign_range(r9); // equal to size() and equal to capacity()\n+  VERIFY( eq(v, a) );\n+  v.resize(1);\n+  v.assign_range(r4); // larger than size(), smaller than capacity()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.clear();\n+  v.resize(4);\n+  v.assign_range(r4); // equal to size(), smaller than capacity()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.shrink_to_fit();\n+  v.assign_range(r9); // larger than capacity()\n+  VERIFY( eq(v, a) );\n+  v.assign_range(Range(a, a));\n+  VERIFY( v.empty() );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<bool>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<bool>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<bool>>();\n+  do_test_a<test_forward_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<bool>>();\n+  do_test_a<test_input_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(bool v) : val(v) { }\n+    operator bool() && { return val; }\n+    bool operator==(bool b) const { return b == val; }\n+    bool val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test_a<rvalue_input_range>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<bool>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc\nnew file mode 100644\nindex 000000000000..e811a1697e02\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc\n@@ -0,0 +1,93 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,1,0,1,0,0,1,0,0};\n+\n+  auto eq = [](const std::vector<bool, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  Range r4(a, a+4);\n+  Range r5(a+4, a+9);\n+\n+  std::vector<bool, Alloc> v;\n+  v.append_range(r4);\n+  VERIFY( eq(v, {a, 4}) );\n+  v.append_range(r5); // larger than v.capacity()\n+  VERIFY( eq(v, a) );\n+  v.append_range(Range(a, a));\n+  VERIFY( eq(v, a) );\n+  v.clear();\n+  v.append_range(Range(a, a));\n+  VERIFY( v.empty() );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<bool>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<bool>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<bool>>();\n+  do_test_a<test_forward_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<bool>>();\n+  do_test_a<test_input_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(bool v) : val(v) { }\n+    operator bool() && { return val; }\n+    bool operator==(bool b) const { return b == val; }\n+    bool val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test_a<rvalue_input_range>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<bool>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc\nnew file mode 100644\nindex 000000000000..82b67cdb8b9b\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc\n@@ -0,0 +1,104 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,1,0,1,0,0,1,0,0};\n+\n+  auto eq = [](const std::vector<bool, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  std::vector<bool, Alloc> v;\n+  v.insert_range(v.begin(), Range(a, a+0));\n+  VERIFY( v.empty() );\n+  VERIFY( v.capacity() == 0 );\n+  v.insert_range(v.begin(), Range(a, a+4));\n+  VERIFY( eq(v, {a, a+4}) );\n+  v.clear();\n+  v.insert_range(v.begin(), Range(a, a+5));\n+  VERIFY( eq(v, {a+4, a+9}) );\n+  v.insert_range(v.begin(), Range(a, a+4));\n+  VERIFY( eq(v, a) );\n+  v.clear();\n+  v.shrink_to_fit();\n+  v.insert_range(v.begin(), Range(a, a+3));\n+  v.insert_range(v.end(), Range(a+6, a+9));\n+  v.insert_range(v.begin()+3, Range(a+3, a+6));\n+  VERIFY( eq(v, a) );\n+  v.resize(3);\n+  v.insert_range(v.begin()+1, Range(a+4, a+9));\n+  v.insert_range(v.begin()+1, Range(a+1, a+3));\n+  v.resize(9);\n+  VERIFY( eq(v, a) );\n+  v.insert_range(v.begin(), Range(a, a));\n+  VERIFY( eq(v, a) );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<bool>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<bool>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<bool>>();\n+  do_test_a<test_forward_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<bool>>();\n+  do_test_a<test_input_sized_range<bool>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<bool, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<bool, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(bool v) : val(v) { }\n+    operator bool() && { return val; }\n+    bool operator==(bool b) const { return b == val; }\n+    bool val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test_a<rvalue_input_range>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<bool>, std::allocator<bool>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc\nnew file mode 100644\nindex 000000000000..d709c77720d2\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc\n@@ -0,0 +1,108 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+void\n+test_deduction_guide(long* p)\n+{\n+  __gnu_test::test_input_range<long> r(p, p);\n+  std::vector v(std::from_range, r);\n+  static_assert(std::is_same_v<decltype(v), std::vector<long>>);\n+\n+  using Alloc = __gnu_test::SimpleAllocator<long>;\n+  Alloc alloc;\n+  std::vector v2(std::from_range, r, alloc);\n+  static_assert(std::is_same_v<decltype(v2), std::vector<long, Alloc>>);\n+}\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test(Alloc alloc)\n+{\n+  // The vector's value_type.\n+  using V = typename std::allocator_traits<Alloc>::value_type;\n+\n+  // The range's value_type.\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,2,3,4,5,6,7,8,9};\n+\n+  auto eq = [](const std::vector<V, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  std::vector<V, Alloc> v0(std::from_range, Range(a, a+0));\n+  VERIFY( v0.empty() );\n+  VERIFY( v0.get_allocator() == Alloc() );\n+\n+  std::vector<V, Alloc> v4(std::from_range, Range(a, a+4));\n+  VERIFY( eq(v4, {a, 4}) );\n+  VERIFY( v4.get_allocator() == Alloc() );\n+\n+  std::vector<V, Alloc> v9(std::from_range, Range(a, a+9), alloc);\n+  VERIFY( eq(v9, {a, 9}) );\n+  VERIFY( v9.get_allocator() == alloc );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range>(std::allocator<int>());\n+  do_test<Range>(__gnu_test::uneq_allocator<int>(42));\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<int>>();\n+  do_test_a<test_forward_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<int>>();\n+  do_test_a<test_input_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(int v) : val(v) { }\n+    operator int() && { return val; }\n+    bool operator==(int b) const { return b == val; }\n+    int val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test<rvalue_input_range, std::allocator<int>>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<int>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc\nnew file mode 100644\nindex 000000000000..ff86cb745573\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc\n@@ -0,0 +1,97 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  // The vector's value_type.\n+  using V = typename std::allocator_traits<Alloc>::value_type;\n+\n+  // The range's value_type.\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,2,3,4,5,6,7,8,9};\n+\n+  auto eq = [](const std::vector<V, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  Range r4(a, a+4);\n+  Range r5(a+4, a+9);\n+\n+  std::vector<V, Alloc> v;\n+  v.append_range(r4);\n+  VERIFY( eq(v, {a, 4}) );\n+  v.append_range(r5); // larger than v.capacity()\n+  VERIFY( eq(v, a) );\n+  v.append_range(Range(a, a));\n+  VERIFY( eq(v, a) );\n+  v.clear();\n+  v.append_range(Range(a, a));\n+  VERIFY( v.empty() );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<int>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<int>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<int>>();\n+  do_test_a<test_forward_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<int>>();\n+  do_test_a<test_input_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(int v) : val(v) { }\n+    operator int() && { return val; }\n+    bool operator==(int b) const { return b == val; }\n+    int val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test<rvalue_input_range, std::allocator<int>>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<int>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc\nnew file mode 100644\nindex 000000000000..c3302e988495\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc\n@@ -0,0 +1,121 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  // The vector's value_type.\n+  using V = typename std::allocator_traits<Alloc>::value_type;\n+\n+  // The range's value_type.\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,2,3,4,5,6,7,8,9};\n+\n+  auto eq = [](const std::vector<V, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  Range r4(a, a+4);\n+  Range r9(a);\n+\n+  // assign to empty vector\n+  std::vector<V, Alloc> v;\n+  v.assign_range(Range(a, a));\n+  VERIFY( v.empty() );\n+  VERIFY( v.capacity() == 0 );\n+  v.assign_range(r4);\n+  VERIFY( eq(v, {a, 4}) );\n+  v.clear();\n+  v.assign_range(r9); // larger than v.capacity()\n+  VERIFY( eq(v, a) );\n+  v.clear();\n+  v.assign_range(r4); // smaller than v.capacity()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.clear();\n+  v.assign_range(r9); // equal to v.capacity()\n+  VERIFY( eq(v, a) );\n+\n+  // assign to non-empty vector\n+  v.assign_range(r4); // smaller than size()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.assign_range(r9); // larger than size(), equal to capacity()\n+  VERIFY( eq(v, a) );\n+  v.resize(1);\n+  v.assign_range(r4); // larger than size(), smaller than capacity()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.clear();\n+  v.resize(4);\n+  v.assign_range(r4); // equal to size(), smaller than capacity()\n+  VERIFY( eq(v, {a, 4}) );\n+  v.shrink_to_fit();\n+  v.assign_range(r9); // larger than capacity()\n+  VERIFY( eq(v, a) );\n+  v.assign_range(Range(a, a));\n+  VERIFY( v.empty() );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<int>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<int>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<int>>();\n+  do_test_a<test_forward_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<int>>();\n+  do_test_a<test_input_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(int v) : val(v) { }\n+    operator int() && { return val; }\n+    bool operator==(int b) const { return b == val; }\n+    int val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test<rvalue_input_range, std::allocator<int>>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<int>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc\nnew file mode 100644\nindex 000000000000..4cfab10eb4c9\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc\n@@ -0,0 +1,108 @@\n+// { dg-do compile { target c++23 } }\n+\n+#include <vector>\n+#include <span>\n+#include <testsuite_hooks.h>\n+#include <testsuite_iterators.h>\n+#include <testsuite_allocator.h>\n+\n+template<typename Range, typename Alloc>\n+constexpr void\n+do_test()\n+{\n+  // The vector's value_type.\n+  using V = typename std::allocator_traits<Alloc>::value_type;\n+\n+  // The range's value_type.\n+  using T = std::ranges::range_value_t<Range>;\n+  T a[]{1,2,3,4,5,6,7,8,9};\n+\n+  auto eq = [](const std::vector<V, Alloc>& l, std::span<T> r) {\n+    if (l.size() != r.size())\n+      return false;\n+    for (auto i = 0u; i < l.size(); ++i)\n+      if (l[i] != r[i])\n+\treturn false;\n+    return true;\n+  };\n+\n+  std::vector<V, Alloc> v;\n+  v.insert_range(v.begin(), Range(a, a));\n+  VERIFY( v.empty() );\n+  VERIFY( v.capacity() == 0 );\n+  v.insert_range(v.begin(), Range(a, a+4));\n+  VERIFY( eq(v, {a, a+4}) );\n+  v.clear();\n+  v.insert_range(v.begin(), Range(a, a+5));\n+  VERIFY( eq(v, {a+4, a+9}) );\n+  v.insert_range(v.begin(), Range(a, a+4));\n+  VERIFY( eq(v, a) );\n+  v.clear();\n+  v.shrink_to_fit();\n+  v.insert_range(v.begin(), Range(a, a+3));\n+  v.insert_range(v.end(), Range(a+6, a+9));\n+  v.insert_range(v.begin()+3, Range(a+3, a+6));\n+  VERIFY( eq(v, a) );\n+  v.resize(3);\n+  v.insert_range(v.begin()+1, Range(a+4, a+9));\n+  v.insert_range(v.begin()+1, Range(a+1, a+3));\n+  v.resize(9);\n+  VERIFY( eq(v, a) );\n+  v.insert_range(v.begin() + 6, Range(a, a));\n+  VERIFY( eq(v, a) );\n+}\n+\n+template<typename Range>\n+void\n+do_test_a()\n+{\n+  do_test<Range, std::allocator<int>>();\n+  do_test<Range, __gnu_test::SimpleAllocator<int>>();\n+}\n+\n+bool\n+test_ranges()\n+{\n+  using namespace __gnu_test;\n+\n+  do_test_a<test_forward_range<int>>();\n+  do_test_a<test_forward_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();\n+\n+  do_test_a<test_input_range<int>>();\n+  do_test_a<test_input_sized_range<int>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>();\n+\n+  do_test_a<test_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>();\n+  do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();\n+\n+  do_test_a<test_forward_range<short>>();\n+  do_test_a<test_input_range<short>>();\n+\n+  // Not lvalue-convertible to bool\n+  struct C {\n+    C(int v) : val(v) { }\n+    operator int() && { return val; }\n+    bool operator==(int b) const { return b == val; }\n+    int val;\n+  };\n+  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;\n+  do_test<rvalue_input_range, std::allocator<int>>();\n+\n+  return true;\n+}\n+\n+constexpr bool\n+test_constexpr()\n+{\n+  // XXX: this doesn't test the non-forward_range code paths are constexpr.\n+  do_test<std::span<short>, std::allocator<int>>;\n+  return true;\n+}\n+\n+int main()\n+{\n+  test_ranges();\n+  static_assert( test_constexpr() );\n+}\ndiff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h\nindex e7f7abe222d5..aafafa710b7e 100644\n--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h\n+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h\n@@ -783,6 +783,26 @@ namespace __gnu_test\n       }\n     };\n \n+  // An input iterator type with an rvalue reference type.\n+  template<typename T>\n+    struct input_iterator_wrapper_rval : input_iterator_wrapper<T>\n+    {\n+      using input_iterator_wrapper<T>::input_iterator_wrapper;\n+\n+      using input_iterator_wrapper<T>::operator++;\n+\n+      input_iterator_wrapper_rval&\n+      operator++()\n+      {\n+\tinput_iterator_wrapper<T>::operator++();\n+\treturn *this;\n+      }\n+\n+      T&&\n+      operator*() const\n+      { return std::move(input_iterator_wrapper<T>::operator*()); }\n+    };\n+\n   // A type meeting the minimum std::range requirements\n   template<typename T, template<typename> class Iter>\n     class test_range\n","prefixes":["v1","1/1"]}