[PATCH][_GLIBCXX_DEBUG] Enhance COW basic_string checks
Jonathan Wakely
jwakely@redhat.com
Tue Jul 21 06:43:50 GMT 2026
On Tue, 21 Jul 2026 at 05:57, François Dumont <frs.dumont@gmail.com> wrote:
>
> Here is the new commit message:
>
> libstdc++: [_GLIBCXX_DEBUG] Improve COW basic_string checks
>
> Put the __glibcxx_requires_valid_range checks at public member level
> so that diagnostics are giving directly the culprit member name.
>
> Add the std::_RequireInputIter constraints on members taking template
> iterator range to avoid the "do the right thing" ambiguity.
>
> libstdc++v3/ChangeLog:
>
> * include/bits/cow_string.h
> (basic_string::_M_replace): New.
> (basic_string(_InputIterator, _InputIterator, const _Alloc&):
> Add std::_RequireInputIter constraint and
> __glibcxx_requires_valid_constructor_range check.
> (basic_string::append(_InputIte, _InputIte): Add
> std::_RequireInputIter
> constraint and __glibcxx_requires_valid_range check. Call
> _M_replace.
> (basic_string::assign(_InputIte, _InputIte): Likewise.
> (basic_string::insert(iterator, _InputIte, _InputIte)):
> Likewise.
> (basic_string::replace(iterator, iterator, _InputIte,
> _InputIte)): Likewise.
> [__cplusplus >= 201103L](basic_string::_S_construct): New.
> (basic_string::_M_replace_dispatch(iterator, iterator,
> _InputIte, _InputIte,
> __false_type)): Remove __glibcxx_requires_valid_range check.
> * include/debug/debug.h
> (__glibcxx_requires_valid_constructor_range): New.
>
> On 7/6/26 22:42, Jonathan Wakely wrote:
> > On Mon, 15 Jun 2026 at 07:07 +0200, François Dumont wrote:
> >> Hi
> >>
> >> libstdc++: [_GLIBCXX_DEBUG] Improve COW basic_string checks
> >>
> >> Put the __glibcxx_requires_valid_range checks at public member level
> >> so that diagnostics are giving directly the invoked member name.
> >>
> >> Add the std::_RequireInputIter constraints on members taking
> >> template
> >> iterator range to avoid the "do the right thing" ambiguity
> >> without the help of __is_integer.
> >>
> >> libstdc++v3/ChangeLog:
> >>
> >> * include/bits/cow_string.h
> >> (basic_string::_M_replace): New.
> >> (basic_string(_InputIterator, _InputIterator, const
> >> _Alloc&): Add
> >> std::_RequireInputIter constraint and
> >> __glibcxx_requires_valid_constructor_range
> >
> > Please fix the line-wrapping here. Try to keep the lines to < 72
> > characters so that when indented by 'git log' they fit below 80.
> >
> >> check.
> >> (basic_string::append(_InputIte, _InputIte): Add
> >> std::_RequireInputIter
> >> constraint and __glibcxx_requires_valid_range check. Call
> >> _M_replace.
> >> (basic_string::assign(_InputIte, _InputIte): Likewise.
> >> (basic_string::insert(iterator, _InputIte, _InputIte)):
> >> Likewise.
> >> (basic_string::replace(iterator, iterator, _InputIte,
> >> _InputIte)): Likewise.
> >> [__cplusplus >= 201103L](basic_string::_S_construct): New.
> >> (basic_string::_M_replace_dispatch(iterator, iterator,
> >> _InputIte, _InputIte,
> >> __false_type)): Remove __glibcxx_requires_valid_range check.
> >> * include/debug/debug.h
> >> (__glibcxx_requires_valid_constructor_range): New.
> >>
> >> Tested under Linux x86_64 with _GLIBCXX_USE_CXX11_ABI=0 and
> >> _GLIBCXX_DEBUG.
> >
> > Did you test C++98 as well as the default -std modes?
>
> I hadn't but now did, ex:
>
> In function:
> std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
> _Traits, _Alloc>::append(_InputIterator, _InputIterator) [with
> _InputIterator = gnu_debug::_Safe_iterator<gnu_cxx::
> normal_iterator<char*, std::vector<char, std::allocator<char> > >,
> std::
> debug::vector<char>, std::random_access_iterator_tag>; _CharT = char;
> _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
>
> Error: function requires a valid iterator range [first, last).
>
> Objects involved in the operation:
> iterator "first" @ 0x7ffc9027e5a0 {
> type = gnu_cxx::normal_iterator<char*, std::vector<char,
> std::allocator<char> > > (mutable iterator);
> state = dereferenceable;
> references sequence with type 'std::debug::vector<char,
> std::allocator<char> >' @ 0x7ffc9027e750
> }
> iterator "last" @ 0x7ffc9027e600 {
> type = gnu_cxx::normal_iterator<char*, std::vector<char,
> std::allocator<char> > > (mutable iterator);
> state = dereferenceable;
> references sequence with type 'std::debug::vector<char,
> std::allocator<char> >' @ 0x7ffc9027e750
> }
> XFAIL: 21_strings/basic_string/debug/append_neg.cc -std=gnu++98
> execution test
>
> >
> > Doesn't this require new symbols to be exported by the linker script?
> >
> I don't think so. Maybe you had in mind the
> __gnu_debug::__check_valid_range but that's a template function
> implemented inline.
You've added a new member function, basic_string::_M_replace. Why
doesn't that need to be exported from the shared library?
Why don't the changes to the signature of basic_string::assign and
basic_string::append change the exported symbols?
>
> Ok to commit ?
More information about the Libstdc++
mailing list