From: Tomasz Kamiński Date: Fri, 24 Apr 2026 03:25:59 +0000 (+0200) Subject: libstdc++: Support integer-class sized range in inplace_vector. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07448319bb645010fac7cc924a2bc287f4f394e9;p=thirdparty%2Fgcc.git 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 Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector index 5ad92332a02..0096bd83a17 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 b79434dd111..b30fc04e4cd 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 +#include #include #include #include @@ -77,7 +78,7 @@ test_iterators() do_test_it(); do_test_it(); do_test_it(); - + do_test_it(); return true; } @@ -108,7 +109,7 @@ do_test_r() return; } #endif - + try { std::inplace_vector v9(std::from_range, Range(a, a+9)); @@ -161,11 +162,65 @@ test_ranges() return true; } +template +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10}; + + std::inplace_vector v1( + std::from_range, std::views::iota(T(1), T(11))); + VERIFY( eq(v1, {a, a+10}) ); + + std::inplace_vector v2( + std::from_range, + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 10; })); + VERIFY( eq(v2, {a, a+10}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits::max(); + try + { + std::inplace_vector v( + std::from_range, std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + + try + { + std::inplace_vector 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(); +#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 c1d867ee1d4..577c1047708 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 +#include #include #include #include @@ -353,6 +354,53 @@ test_assigns() test_resize(); } +template +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10}; + + std::inplace_vector v; + v.assign_range(std::views::iota(T(1), T(11))); + VERIFY( eq(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(v, {a, a+10}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits::max(); + try + { + v.assign_range(std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq(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(); } + + test_iota(); +#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 e5a482cdc65..bde66847a34 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 +#include #include #include #include @@ -506,6 +507,8 @@ test_insert_repeated() #endif } + + template constexpr void test_inserts() @@ -526,16 +529,102 @@ test_inserts() test_insert_iterators(); test_insert_iterators(); -test_insert_initializer_list(); -test_insert_repeated(); + test_insert_initializer_list(); + test_insert_repeated(); +} + +template +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + + std::inplace_vector v; + auto it = v.insert_range(v.begin(), std::views::iota(T(1), T(11))); + VERIFY( eq(v, {a, a+10}) ); + VERIFY( it == v.begin() ); + + v.append_range(std::views::iota(T(11), T(16))); + VERIFY( eq(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(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(v, {a, 15}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits::max(); + try + { + v.insert_range(v.end(), std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq(v, {a, 15}) ); + + try + { + v.append_range(std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq(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(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(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(); #ifdef __cpp_lib_constexpr_inplace_vector @@ -545,6 +634,11 @@ auto test_all = []{ test_add_to_full<4, X>(); test_inserts(); } + + test_iota(); +#ifdef __SIZEOF_INT128__ + test_iota<__int128>(); +#endif return true; };