[PATCH] libstdc++: Fix-self element self-assigments when insertint an empty range [PR121313]
Jonathan Wakely
jwakely.gcc@gmail.com
Fri Aug 15 10:23:28 GMT 2025
On Thu, 14 Aug 2025, 15:31 Patrick Palka, <ppalka@redhat.com> wrote:
> On Thu, 14 Aug 2025, Tomasz Kamiński wrote:
>
> Typo in subject line, "inserting"
>
> > For __n == 0, the elements where self move-assigned by
> > std::move_backward(__ins, __old_finish - __n, __old_finish).
>
> s/where/were?
>
> LGTM besides that.
>
Yeah, ok for trunk and gcc-15 with those tweaks.
> >
> > PR libstdc++/121313
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/bits/vector.tcc (vector::insert_range): Add check for
> > empty size.
> > * testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
> > New tests.
> > ---
> > Testing on x86_64-linux. Newly added test passed.
> >
> > OK for trunk and v15.
> >
> > libstdc++-v3/include/bits/vector.tcc | 10 ++--
> > .../vector/modifiers/insert/insert_range.cc | 50 +++++++++++++++++++
> > 2 files changed, 57 insertions(+), 3 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/vector.tcc
> b/libstdc++-v3/include/bits/vector.tcc
> > index 70ead1d7083..1543ce9cd77 100644
> > --- a/libstdc++-v3/include/bits/vector.tcc
> > +++ b/libstdc++-v3/include/bits/vector.tcc
> > @@ -1007,17 +1007,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >
> > if constexpr (ranges::forward_range<_Rg>)
> > {
> > + const auto __ins_idx = __pos - cbegin();
> > + // Number of new elements to insert:
> > + const auto __n = size_type(ranges::distance(__rg));
> > + if (__n == 0)
> > + return begin() + __ins_idx;
> > +
> > // Start of existing elements:
> > pointer __old_start = this->_M_impl._M_start;
> > // End of existing elements:
> > pointer __old_finish = this->_M_impl._M_finish;
> > // Insertion point:
> > - const auto __ins_idx = __pos - cbegin();
> > pointer __ins = __old_start + __ins_idx;
> > - // Number of new elements to insert:
> > - const auto __n = size_type(ranges::distance(__rg));
> > // Number of elements that can fit in unused capacity:
> > const auto __cap = this->_M_impl._M_end_of_storage -
> __old_finish;
> > +
> > if (__cap >= __n)
> > {
> > // Number of existing elements after insertion point:
> > diff --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
> > index 506bebbe519..e4b5982188f 100644
> > ---
> a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
> > +++
> b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
> > @@ -99,8 +99,58 @@ test_ranges()
> > return true;
> > }
> >
> > +struct SelfAssignChecker {
> > + static int moveCounter;
> > + static int copyCounter;
> > +
> > + SelfAssignChecker() = default;
> > + constexpr SelfAssignChecker(int v) : val(v) { }
> > + SelfAssignChecker(const SelfAssignChecker&) = default;
> > + SelfAssignChecker(SelfAssignChecker&&) = default;
> > +
> > + SelfAssignChecker operator=(const SelfAssignChecker& rhs)
> > + {
> > + if (this == &rhs)
> > + ++copyCounter;
> > + this->val = rhs.val;
> > + return *this;
> > + }
> > +
> > + SelfAssignChecker operator=(SelfAssignChecker&& rhs)
> > + {
> > + if (this == &rhs)
> > + ++moveCounter;
> > + this->val = rhs.val;
> > + return *this;
> > + }
> > +
> > + int val;
> > +
> > + friend bool operator==(SelfAssignChecker, SelfAssignChecker) =
> default;
> > +};
> > +
> > +int SelfAssignChecker::moveCounter = 0;
> > +int SelfAssignChecker::copyCounter = 0;
> > +
> > +void
> > +test_pr121313()
> > +{
> > + using namespace __gnu_test;
> > +
> > + SelfAssignChecker::copyCounter = SelfAssignChecker::moveCounter = 0;
> > + do_test<test_forward_range<int>, std::allocator<SelfAssignChecker>>();
> > + VERIFY( SelfAssignChecker::moveCounter == 0 );
> > + VERIFY( SelfAssignChecker::copyCounter == 0 );
> > +
> > + SelfAssignChecker::copyCounter = SelfAssignChecker::moveCounter = 0;
> > + do_test<test_input_range<int>, std::allocator<SelfAssignChecker>>();
> > + VERIFY( SelfAssignChecker::moveCounter == 0 );
> > + VERIFY( SelfAssignChecker::copyCounter == 0 );
> > +}
> > +
> > int main()
> > {
> > test_ranges();
> > + test_pr121313();
> > static_assert( test_ranges() );
> > }
> > --
> > 2.49.0
> >
> >
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250815/4a7def24/attachment-0001.htm>
More information about the Libstdc++
mailing list