https://gcc.gnu.org/g:07448319bb645010fac7cc924a2bc287f4f394e9

commit r17-636-g07448319bb645010fac7cc924a2bc287f4f394e9
Author: Tomasz Kamiński <[email protected]>
Date:   Fri Apr 24 05:25:59 2026 +0200

    libstdc++: Support integer-class sized range in inplace_vector.
    
    Simply cast size of the input range to size_t, after verifying that
    it fits in remaining capacity, and thus in size_t.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/inplace_vector (inplace_vector::assign_range)
            (inplace_vector::append_range): Cast ranges::distance(__rg)
            to size_t.
            * testsuite/23_containers/inplace_vector/cons/from_range.cc: New
            test for ranges with integer-class size_type.
            * testsuite/23_containers/inplace_vector/modifiers/assign.cc:
            Likewise.
            * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc:
            Likewise.
    
    Reviewed-by: Patrick Palka <[email protected]>
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 libstdc++-v3/include/std/inplace_vector            |  12 ++-
 .../inplace_vector/cons/from_range.cc              |  59 +++++++++++-
 .../inplace_vector/modifiers/assign.cc             |  55 ++++++++++-
 .../inplace_vector/modifiers/multi_insert.cc       | 106 +++++++++++++++++++--
 4 files changed, 219 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/std/inplace_vector 
b/libstdc++-v3/include/std/inplace_vector
index 5ad92332a02c..0096bd83a175 100644
--- a/libstdc++-v3/include/std/inplace_vector
+++ b/libstdc++-v3/include/std/inplace_vector
@@ -248,9 +248,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        {
          if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
            {
-             const auto __sz = ranges::distance(__rg);
-             if (__sz > _Nm)
+             const auto __len = ranges::distance(__rg);
+             if (__len > _Nm)
                __throw_bad_alloc();
+
+             const size_t __sz = size_t(__len);
              if (__sz <= size())
                {
                  ranges::copy_n(ranges::begin(__rg), __sz, data());
@@ -523,9 +525,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        {
          if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
            {
-             const auto __sz = ranges::distance(__rg);
-             if (__sz > (_Nm - size()))
+             const auto __len = ranges::distance(__rg);
+             if (__len > (_Nm - size()))
                __throw_bad_alloc();
+
+             const size_t __sz = size_t(__len);
              // Bounded on output range due PR121143
              ranges::uninitialized_copy(
                ranges::begin(__rg), unreachable_sentinel,
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
index b79434dd1119..b30fc04e4cdd 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
@@ -2,6 +2,7 @@
 
 #include <inplace_vector>
 
+#include <ranges>
 #include <span>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
@@ -77,7 +78,7 @@ test_iterators()
   do_test_it<int, input_iterator_wrapper>();
   do_test_it<int, forward_iterator_wrapper>();
   do_test_it<int, random_access_iterator_wrapper>();
-  
+
   do_test_it<short, forward_iterator_wrapper>();
   return true;
 }
@@ -108,7 +109,7 @@ do_test_r()
     return;
   }
 #endif
-  
+
   try
   {
     std::inplace_vector<V, 5> v9(std::from_range, Range(a, a+9));
@@ -161,11 +162,65 @@ test_ranges()
   return true;
 }
 
+template<typename T>
+constexpr void
+test_iota()
+{
+  T a[]{1,2,3,4,5,6,7,8,9,10};
+
+  std::inplace_vector<T, 10> v1(
+    std::from_range, std::views::iota(T(1), T(11)));
+  VERIFY( eq<T>(v1, {a, a+10}) );
+
+  std::inplace_vector<T, 10> v2(
+    std::from_range,
+    std::views::iota(T(1))
+    | std::views::as_input
+    | std::views::take_while([](T t) { return t <= 10; }));
+  VERIFY( eq<T>(v2, {a, a+10}) );
+
+#ifdef __cpp_exceptions
+#ifndef __cpp_lib_constexpr_exceptions
+  if consteval {
+    return;
+  }
+#endif
+  constexpr T max = std::numeric_limits<T>::max();
+  try
+  {
+    std::inplace_vector<T, 10> v(
+      std::from_range, std::views::iota(T(0), max));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+
+  try
+  {
+    std::inplace_vector<T, 10> v(
+      std::from_range,
+      std::views::iota(T(0))
+      | std::views::as_input
+      | std::views::take_while([](T t) { return t < 15; }));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+#endif
+}
+
 int main()
 {
   auto test_all = [] {
     test_iterators();
     test_ranges();
+
+    test_iota<long long>();
+#ifdef __SIZEOF_INT128__
+    test_iota<__int128>();
+#endif
     return true;
   };
 
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
index c1d867ee1d41..577c10477086 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
@@ -2,6 +2,7 @@
 
 #include <inplace_vector>
 
+#include <ranges>
 #include <span>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
@@ -353,6 +354,53 @@ test_assigns()
   test_resize<T>();
 }
 
+template<typename T>
+constexpr void
+test_iota()
+{
+  T a[]{1,2,3,4,5,6,7,8,9,10};
+
+  std::inplace_vector<T, 10> v;
+  v.assign_range(std::views::iota(T(1), T(11)));
+  VERIFY( eq<T>(v, {a, a+10}) );
+
+  v.assign_range(
+    std::views::iota(T(1))
+    | std::views::as_input
+    | std::views::take_while([](T t) { return t <= 10; }));
+  VERIFY( eq<T>(v, {a, a+10}) );
+
+#ifdef __cpp_exceptions
+#ifndef __cpp_lib_constexpr_exceptions
+  if consteval {
+    return;
+  }
+#endif
+  constexpr T max = std::numeric_limits<T>::max();
+  try
+  {
+    v.assign_range(std::views::iota(T(0), max));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+  VERIFY( eq<T>(v, {a, 10}) );
+
+  try
+  {
+    v.assign_range(
+      std::views::iota(T(0))
+      | std::views::as_input
+      | std::views::take_while([](T t) { return t < 15; }));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+#endif
+}
+
 int main()
 {
   auto test_all = [] {
@@ -368,10 +416,15 @@ int main()
       test_assign_empty<2, X>();
       test_assigns<X>();
     }
+
+    test_iota<long long>();
+#ifdef __SIZEOF_INT128__
+    test_iota<__int128>();
+#endif
+
     return true;
   };
 
-
   test_all();
   static_assert(test_all());
 }
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
index e5a482cdc65d..bde66847a34c 100644
--- 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
@@ -2,6 +2,7 @@
 
 #include <inplace_vector>
 
+#include <ranges>
 #include <span>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
@@ -506,6 +507,8 @@ test_insert_repeated()
 #endif
 }
 
+
+
 template<typename T>
 constexpr void
 test_inserts()
@@ -526,16 +529,102 @@ test_inserts()
   test_insert_iterators<T, forward_iterator_wrapper>();
   test_insert_iterators<T, random_access_iterator_wrapper>();
 
-test_insert_initializer_list<T>();
-test_insert_repeated<T>();
+  test_insert_initializer_list<T>();
+  test_insert_repeated<T>();
+}
+
+template<typename T>
+constexpr void
+test_iota()
+{
+  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+  std::inplace_vector<T, 20> v;
+  auto it = v.insert_range(v.begin(), std::views::iota(T(1), T(11)));
+  VERIFY( eq<T>(v, {a, a+10}) );
+  VERIFY( it == v.begin() );
+
+  v.append_range(std::views::iota(T(11), T(16)));
+  VERIFY( eq<T>(v, {a, 15}) );
+
+  v.clear();
+  it = v.insert_range(v.begin(),
+    std::views::iota(T(1))
+    | std::views::as_input
+    | std::views::take_while([](T t) { return t <= 10; }));
+  VERIFY( eq<T>(v, {a, a+10}) );
+  VERIFY( it == v.begin() );
+
+  v.append_range(
+    std::views::iota(T(11))
+    | std::views::as_input
+    | std::views::take_while([](T t) { return t <= 15; }));
+  VERIFY( eq<T>(v, {a, 15}) );
+
+#ifdef __cpp_exceptions
+#ifndef __cpp_lib_constexpr_exceptions
+  if consteval {
+    return;
+  }
+#endif
+  constexpr T max = std::numeric_limits<T>::max();
+  try
+  {
+    v.insert_range(v.end(), std::views::iota(T(0), max));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+  VERIFY( eq<T>(v, {a, 15}) );
+
+  try
+  {
+    v.append_range(std::views::iota(T(0), max));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+  VERIFY( eq<T>(v, {a, 15}) );
+
+  auto vc = v;
+  try
+  {
+    vc.insert_range(vc.end(),
+      std::views::iota(T(1))
+      | std::views::as_input
+      | std::views::take_while([](T t) { return t <= 20; }));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+  VERIFY( prefix<T>(vc, {a, 15}) );
+
+  vc = v;
+  try
+  {
+    vc.append_range(
+      std::views::iota(T(1))
+      | std::views::as_input
+      | std::views::take_while([](T t) { return t <= 20; }));
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+  VERIFY( prefix<T>(vc, {a, 15}) );
+
+#endif
 }
 
 int main()
 {
-auto test_all = []{
-  test_add_to_full<0, int>();
-  test_add_to_full<0, X>();
-  test_add_to_full<4, int>();
+  auto test_all = []{
+    test_add_to_full<0, int>();
+    test_add_to_full<0, X>();
+    test_add_to_full<4, int>();
 
     test_inserts<int>();
 #ifdef __cpp_lib_constexpr_inplace_vector
@@ -545,6 +634,11 @@ auto test_all = []{
       test_add_to_full<4, X>();
       test_inserts<X>();
     }
+
+    test_iota<long long>();
+#ifdef __SIZEOF_INT128__
+    test_iota<__int128>();
+#endif
     return true;
   };

Reply via email to