[v2] libstdc++: Export explicit instantiations for C++20 members of std::string
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-arm |
fail
|
Test failed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
fail
|
Test failed
|
Commit Message
The C++20 standard added new starts_with and ends_with members to
std::basic_string, which were not previously instantiated in the library.
This meant that the extern template declarations had to be disabled for
C++20 mode. With this patch the new members are instantiated in the
library and so the explicit instantiation declarations can be used for
C++20.
Furthermore, basic_string default constructor is now constrained with
is_default_constructible_v<_Alloc> constrains, that is included in
mangled name, so we also need to instantiate and export it.
The new members added by C++23 are still not exported, and so the
explicit instantiation declarations are still disabled for C++23.
libstdc++-v3/ChangeLog:
* config/abi/pre/gnu.ver (GLIBCXX_3.4): Make string exports
less greedy.
(GLIBCXX_3.4.26): Export basic_string default constructor and
starts_with and ends_with members.
* include/bits/basic_string.h: Update __cpluplus checks for C++20.
* include/bits/cow_string.h: Likewise.
* include/bits/basic_string.tcc: Declare explicit instantiations
for C++20 as well as earlier dialects.
* src/c++20/Makefile.am: Add cow-string-inst.cc and
string-inst.cc source files.
* src/c++20/Makefile.in: Regenerate.
* src/c++20/string-inst.cc: New file defining explicit
instantiations for basic_string default constructor and starts_with,
ends_with methods added in C++20
* src/c++20/cow-string-inst.cc: Version of above for cow-stings.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
---
v2 updates the years in copyright and standard reference,
as suggested.
Tested after Jakub's fix for PR124754 on x86_64-linux,
and all test passed. Same for test -O0.
OK for trunk?
libstdc++-v3/config/abi/pre/gnu.ver | 31 ++++++++++--
libstdc++-v3/include/bits/basic_string.h | 2 +-
libstdc++-v3/include/bits/basic_string.tcc | 17 ++++---
libstdc++-v3/include/bits/cow_string.h | 4 +-
libstdc++-v3/src/c++20/Makefile.am | 16 +++++-
libstdc++-v3/src/c++20/Makefile.in | 15 ++++--
libstdc++-v3/src/c++20/cow-string-inst.cc | 34 +++++++++++++
libstdc++-v3/src/c++20/string-inst.cc | 59 ++++++++++++++++++++++
8 files changed, 158 insertions(+), 20 deletions(-)
create mode 100644 libstdc++-v3/src/c++20/cow-string-inst.cc
create mode 100644 libstdc++-v3/src/c++20/string-inst.cc
Comments
On Sat, 4 Apr 2026, 17:26 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
> The C++20 standard added new starts_with and ends_with members to
> std::basic_string, which were not previously instantiated in the library.
> This meant that the extern template declarations had to be disabled for
> C++20 mode. With this patch the new members are instantiated in the
> library and so the explicit instantiation declarations can be used for
> C++20.
>
> Furthermore, basic_string default constructor is now constrained with
> is_default_constructible_v<_Alloc> constrains, that is included in
> mangled name, so we also need to instantiate and export it.
>
> The new members added by C++23 are still not exported, and so the
> explicit instantiation declarations are still disabled for C++23.
>
> libstdc++-v3/ChangeLog:
>
> * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make string exports
> less greedy.
> (GLIBCXX_3.4.26): Export basic_string default constructor and
> starts_with and ends_with members.
> * include/bits/basic_string.h: Update __cpluplus checks for C++20.
> * include/bits/cow_string.h: Likewise.
> * include/bits/basic_string.tcc: Declare explicit instantiations
> for C++20 as well as earlier dialects.
> * src/c++20/Makefile.am: Add cow-string-inst.cc and
> string-inst.cc source files.
> * src/c++20/Makefile.in: Regenerate.
> * src/c++20/string-inst.cc: New file defining explicit
> instantiations for basic_string default constructor and
> starts_with,
> ends_with methods added in C++20
> * src/c++20/cow-string-inst.cc: Version of above for cow-stings.
>
> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
> ---
> v2 updates the years in copyright and standard reference,
> as suggested.
>
> Tested after Jakub's fix for PR124754 on x86_64-linux,
> and all test passed. Same for test -O0.
> OK for trunk?
>
OK, thanks
> libstdc++-v3/config/abi/pre/gnu.ver | 31 ++++++++++--
> libstdc++-v3/include/bits/basic_string.h | 2 +-
> libstdc++-v3/include/bits/basic_string.tcc | 17 ++++---
> libstdc++-v3/include/bits/cow_string.h | 4 +-
> libstdc++-v3/src/c++20/Makefile.am | 16 +++++-
> libstdc++-v3/src/c++20/Makefile.in | 15 ++++--
> libstdc++-v3/src/c++20/cow-string-inst.cc | 34 +++++++++++++
> libstdc++-v3/src/c++20/string-inst.cc | 59 ++++++++++++++++++++++
> 8 files changed, 158 insertions(+), 20 deletions(-)
> create mode 100644 libstdc++-v3/src/c++20/cow-string-inst.cc
> create mode 100644 libstdc++-v3/src/c++20/string-inst.cc
>
> diff --git a/libstdc++-v3/config/abi/pre/gnu.ver
> b/libstdc++-v3/config/abi/pre/gnu.ver
> index fb968e122d8..2ff2aa02383 100644
> --- a/libstdc++-v3/config/abi/pre/gnu.ver
> +++ b/libstdc++-v3/config/abi/pre/gnu.ver
> @@ -268,9 +268,11 @@ GLIBCXX_3.4 {
> _ZNSspLE[PRc]*;
> _ZNKSs[0-3][a-b]*;
> _ZNKSs[5-9][a-b]*;
> - _ZNKSs[0-9][d-e]*;
> + _ZNKSs[0-8][d-e]*;
> _ZNKSs[0-9][g-z]*;
> - _ZNKSs[0-9][0-9][a-z]*;
> + _ZNKSs11_[MS]_*;
> + _ZNKSs1[2-8][a-z]*;
> + _ZNKSs[2-9][0-9][a-z]*;
> _ZNKSs4find*;
> _ZNKSs[abd-z]*;
> _ZNKSs4_Rep12_M_is_leakedEv;
> @@ -339,9 +341,11 @@ GLIBCXX_3.4 {
> _ZNSbIwSt11char_traitsIwESaIwEEpLE[PRw]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[0-3][a-b]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[5-9][a-b]*;
> - _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][d-e]*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE[0-8][d-e]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][g-z]*;
> - _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][0-9][a-z]*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[abd-z]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE4find*;
> _ZNKSbIwSt11char_traitsIwESaIwEE4_Rep12_M_is_leakedEv;
> @@ -1811,7 +1815,9 @@ GLIBCXX_3.4.21 {
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev;
>
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]I[PN]*;
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[Daip]*;
> - _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[1-9]*;
> +
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11_[MS]_*;
> +
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE1[2-9]*;
> + _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[2-8]*;
>
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEixE[jmy];
>
> # operator+ for ABI-tagged std::basic_string
> @@ -2587,6 +2593,21 @@ GLIBCXX_3.4.35 {
> _ZNSt12__cow_stringaSEOS_;
> _ZNKSt12__cow_string5c_strEv;
>
> + # basic_string::starts_with
> + _ZNKSs11starts_with*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE11starts_with*;
> +
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11starts_with*;
> +
> + # basic_string::ends_with
> + _ZNKSs9ends_with*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE9ends_with*;
> +
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE9ends_with*;
> +
> + # basic_string::basic_string() noexcept
> is_default_constructible<Allocator>;
> + _ZNSsC[12]EvQ26is_default_constructible_vIT1_E;
> +
> _ZNSbIwSt11char_traitsIwESaIwEEC[12]EvQ26is_default_constructible_vIT1_E;
> +
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[1-2]EvQ26is_default_constructible_vIT1_E;
> +
> #if defined (_WIN32) && !defined (__CYGWIN__)
> _ZSt19__get_once_callablev;
> _ZSt15__get_once_callv;
> diff --git a/libstdc++-v3/include/bits/basic_string.h
> b/libstdc++-v3/include/bits/basic_string.h
> index 202a911f9ef..af4e5d9486f 100644
> --- a/libstdc++-v3/include/bits/basic_string.h
> +++ b/libstdc++-v3/include/bits/basic_string.h
> @@ -1331,7 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> /**
> * Equivalent to shrink_to_fit().
> */
> -#if __cplusplus > 201703L
> +#if __cplusplus >= 202002L
> [[deprecated("use shrink_to_fit() instead")]]
> #endif
> _GLIBCXX20_CONSTEXPR
> diff --git a/libstdc++-v3/include/bits/basic_string.tcc
> b/libstdc++-v3/include/bits/basic_string.tcc
> index a223edf67ac..b00dd550237 100644
> --- a/libstdc++-v3/include/bits/basic_string.tcc
> +++ b/libstdc++-v3/include/bits/basic_string.tcc
> @@ -1031,12 +1031,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> // Inhibit implicit instantiations for required instantiations,
> // which are defined via explicit instantiations elsewhere.
> #if _GLIBCXX_EXTERN_TEMPLATE
> - // The explicit instantiation definitions in src/c++11/string-inst.cc
> and
> - // src/c++17/string-inst.cc only instantiate the members required for
> C++17
> - // and earlier standards (so not C++20's starts_with and ends_with).
> - // Suppress the explicit instantiation declarations for C++20, so C++20
> + // The explicit instantiation definitions in src/c++11/string-inst.cc,
> + // src/c++17/string-inst.cc and src/c++20/string-inst.cc only
> instantiate
> + // the members required for C++20 and earlier standards (so not C++23's
> + // contains).
> + // Suppress the explicit instantiation declarations for C++23, so C++23
> // code will implicitly instantiate std::string and std::wstring as
> needed.
> -# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
> +# if __cplusplus <= 202002L && _GLIBCXX_EXTERN_TEMPLATE > 0
> extern template class basic_string<char>;
> # elif ! _GLIBCXX_USE_CXX11_ABI
> // Still need to prevent implicit instantiation of the COW empty rep,
> @@ -1044,7 +1045,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> extern template basic_string<char>::size_type
> basic_string<char>::_Rep::_S_empty_rep_storage[];
> # elif _GLIBCXX_EXTERN_TEMPLATE > 0
> - // Export _M_replace_cold even for C++20.
> + // Export _M_replace_cold even for C++23.
> extern template void
> basic_string<char>::_M_replace_cold(char *, size_type, const char*,
> const size_type, const size_type);
> @@ -1064,13 +1065,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> getline(basic_istream<char>&, string&);
>
> #ifdef _GLIBCXX_USE_WCHAR_T
> -# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
> +# if __cplusplus <= 202002L && _GLIBCXX_EXTERN_TEMPLATE > 0
> extern template class basic_string<wchar_t>;
> # elif ! _GLIBCXX_USE_CXX11_ABI
> extern template basic_string<wchar_t>::size_type
> basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
> # elif _GLIBCXX_EXTERN_TEMPLATE > 0
> - // Export _M_replace_cold even for C++20.
> + // Export _M_replace_cold even for C++23.
> extern template void
> basic_string<wchar_t>::_M_replace_cold(wchar_t*, size_type, const
> wchar_t*,
> const size_type, const
> size_type);
> diff --git a/libstdc++-v3/include/bits/cow_string.h
> b/libstdc++-v3/include/bits/cow_string.h
> index df71185e556..7c945f6b998 100644
> --- a/libstdc++-v3/include/bits/cow_string.h
> +++ b/libstdc++-v3/include/bits/cow_string.h
> @@ -1080,7 +1080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> reserve(size_type __res_arg);
>
> /// Equivalent to shrink_to_fit().
> -#if __cplusplus > 201703L
> +#if __cplusplus >= 202002L
> [[deprecated("use shrink_to_fit() instead")]]
> #endif
> void
> @@ -3194,7 +3194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> return __r;
> }
>
> -#if __cplusplus > 201703L
> +#if __cplusplus >= 202002L
> bool
> starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
> { return __sv_type(this->data(), this->size()).starts_with(__x); }
> diff --git a/libstdc++-v3/src/c++20/Makefile.am
> b/libstdc++-v3/src/c++20/Makefile.am
> index 0061678dc0f..af5d2fa4057 100644
> --- a/libstdc++-v3/src/c++20/Makefile.am
> +++ b/libstdc++-v3/src/c++20/Makefile.am
> @@ -27,10 +27,19 @@ noinst_LTLIBRARIES = libc++20convenience.la
>
> headers =
>
> +if ENABLE_DUAL_ABI
> +extra_string_inst_sources = cow-string-inst.cc
> +else
> +extra_string_inst_sources =
> +endif
> +
> +
> if ENABLE_EXTERN_TEMPLATE
> # XTEMPLATE_FLAGS = -fno-implicit-templates
> inst_sources = \
> - sstream-inst.cc
> + sstream-inst.cc \
> + string-inst.cc \
> + $(extra_string_inst_sources)
> else
> # XTEMPLATE_FLAGS =
> inst_sources =
> @@ -40,6 +49,11 @@ sources = tzdb.cc format.cc atomic.cc clock.cc
> syncbuf.cc
>
> vpath % $(top_srcdir)/src/c++20
>
> +if ENABLE_DUAL_ABI
> +# These files should be rebuilt if the .cc prerequisite changes.
> +cow-string-inst.lo cow-string-inst.o: string-inst.cc
> +endif
> +
> if USE_STATIC_TZDATA
> tzdata.zi.h: $(top_srcdir)/src/c++20/tzdata.zi
> echo 'static const char tzdata_chars[] = R"__libstdcxx__(' > $@.tmp
> diff --git a/libstdc++-v3/src/c++20/Makefile.in
> b/libstdc++-v3/src/c++20/Makefile.in
> index f481ad08edb..a2386ec7ee0 100644
> --- a/libstdc++-v3/src/c++20/Makefile.in
> +++ b/libstdc++-v3/src/c++20/Makefile.in
> @@ -124,9 +124,11 @@ CONFIG_CLEAN_VPATH_FILES =
> LTLIBRARIES = $(noinst_LTLIBRARIES)
> libc__20convenience_la_LIBADD =
> am__objects_1 = tzdb.lo format.lo atomic.lo clock.lo syncbuf.lo
> -@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = sstream-inst.lo
> +@ENABLE_DUAL_ABI_TRUE@am__objects_2 = cow-string-inst.lo
> +@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_3 = sstream-inst.lo \
> +@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo $(am__objects_2)
> @GLIBCXX_HOSTED_TRUE@am_libc__20convenience_la_OBJECTS = \
> -@GLIBCXX_HOSTED_TRUE@ $(am__objects_1) $(am__objects_2)
> +@GLIBCXX_HOSTED_TRUE@ $(am__objects_1) $(am__objects_3)
> libc__20convenience_la_OBJECTS = $(am_libc__20convenience_la_OBJECTS)
> AM_V_lt = $(am__v_lt_@AM_V@)
> am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
> @@ -428,12 +430,16 @@ AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS)
> # Convenience library for C++20 runtime.
> noinst_LTLIBRARIES = libc++20convenience.la
> headers =
> +@ENABLE_DUAL_ABI_FALSE@extra_string_inst_sources =
> +@ENABLE_DUAL_ABI_TRUE@extra_string_inst_sources = cow-string-inst.cc
> # XTEMPLATE_FLAGS =
> @ENABLE_EXTERN_TEMPLATE_FALSE@inst_sources =
>
> # XTEMPLATE_FLAGS = -fno-implicit-templates
> @ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \
> -@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc
> +@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc \
> +@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.cc \
> +@ENABLE_EXTERN_TEMPLATE_TRUE@ $(extra_string_inst_sources)
>
> sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc
> @GLIBCXX_HOSTED_FALSE@libc__20convenience_la_SOURCES =
> @@ -747,6 +753,9 @@ uninstall-am:
>
> vpath % $(top_srcdir)/src/c++20
>
> +# These files should be rebuilt if the .cc prerequisite changes.
> +@ENABLE_DUAL_ABI_TRUE@cow-string-inst.lo cow-string-inst.o:
> string-inst.cc
> +
> @USE_STATIC_TZDATA_TRUE@tzdata.zi.h: $(top_srcdir)/src/c++20/tzdata.zi
> @USE_STATIC_TZDATA_TRUE@ echo 'static const char tzdata_chars[] =
> R"__libstdcxx__(' > $@.tmp
> @USE_STATIC_TZDATA_TRUE@ cat $^ >> $@.tmp
> diff --git a/libstdc++-v3/src/c++20/cow-string-inst.cc
> b/libstdc++-v3/src/c++20/cow-string-inst.cc
> new file mode 100644
> index 00000000000..f3f411f5d0a
> --- /dev/null
> +++ b/libstdc++-v3/src/c++20/cow-string-inst.cc
> @@ -0,0 +1,34 @@
> +// Reference-counted COW string instantiations for C++20 -*- C++ -*-
> +
> +// Copyright (C) 2026 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library. This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +// GNU General Public License for more details.
> +
> +// Under Section 7 of GPL version 3, you are granted additional
> +// permissions described in the GCC Runtime Library Exception, version
> +// 3.1, as published by the Free Software Foundation.
> +
> +// You should have received a copy of the GNU General Public License and
> +// a copy of the GCC Runtime Library Exception along with this program;
> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +// <http://www.gnu.org/licenses/>.
> +
> +//
> +// ISO C++ 14882:2020 21 Strings library
> +//
> +
> +#define _GLIBCXX_USE_CXX11_ABI 0
> +#include "string-inst.cc"
> +
> +#if ! _GLIBCXX_USE_DUAL_ABI
> +# error This file should not be compiled for this configuration.
> +#endif
> diff --git a/libstdc++-v3/src/c++20/string-inst.cc
> b/libstdc++-v3/src/c++20/string-inst.cc
> new file mode 100644
> index 00000000000..2bdd77c78a4
> --- /dev/null
> +++ b/libstdc++-v3/src/c++20/string-inst.cc
> @@ -0,0 +1,59 @@
> +// string instantiations for C++20 -*- C++ -*-
> +
> +// Copyright (C) 2026 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library. This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +// GNU General Public License for more details.
> +
> +// Under Section 7 of GPL version 3, you are granted additional
> +// permissions described in the GCC Runtime Library Exception, version
> +// 3.1, as published by the Free Software Foundation.
> +
> +// You should have received a copy of the GNU General Public License and
> +// a copy of the GCC Runtime Library Exception along with this program;
> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +// <http://www.gnu.org/licenses/>.
> +
> +//
> +// ISO C++ 14882:2020 21 Strings library
> +//
> +
> +#ifndef _GLIBCXX_USE_CXX11_ABI
> +// Instantiations in this file use the new SSO std::string ABI unless
> included
> +// by another file which defines _GLIBCXX_USE_CXX11_ABI=0.
> +# define _GLIBCXX_USE_CXX11_ABI 1
> +#endif
> +
> +#include <string>
> +
> +namespace std _GLIBCXX_VISIBILITY(default)
> +{
> +_GLIBCXX_BEGIN_NAMESPACE_VERSION
> +template basic_string<char>::basic_string() noexcept;
> +template bool basic_string<char>::starts_with(string_view) const noexcept;
> +template bool basic_string<char>::starts_with(char) const noexcept;
> +template bool basic_string<char>::starts_with(const char*) const noexcept;
> +template bool basic_string<char>::ends_with(string_view) const noexcept;
> +template bool basic_string<char>::ends_with(char) const noexcept;
> +template bool basic_string<char>::ends_with(const char*) const noexcept;
> +
> +#ifdef _GLIBCXX_USE_WCHAR_T
> +template basic_string<wchar_t>::basic_string() noexcept;
> +template bool basic_string<wchar_t>::starts_with(wstring_view) const
> noexcept;
> +template bool basic_string<wchar_t>::starts_with(wchar_t) const noexcept;
> +template bool basic_string<wchar_t>::starts_with(const wchar_t*) const
> noexcept;
> +template bool basic_string<wchar_t>::ends_with(wstring_view) const
> noexcept;
> +template bool basic_string<wchar_t>::ends_with(wchar_t) const noexcept;
> +template bool basic_string<wchar_t>::ends_with(const wchar_t*) const
> noexcept;
> +#endif
> +
> +_GLIBCXX_END_NAMESPACE_VERSION
> +} // namespace std
> --
> 2.53.0
>
>
Hi Jonathan,
> On Sat, 4 Apr 2026, 17:26 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
>
>> The C++20 standard added new starts_with and ends_with members to
>> std::basic_string, which were not previously instantiated in the library.
>> This meant that the extern template declarations had to be disabled for
>> C++20 mode. With this patch the new members are instantiated in the
>> library and so the explicit instantiation declarations can be used for
>> C++20.
>>
>> Furthermore, basic_string default constructor is now constrained with
>> is_default_constructible_v<_Alloc> constrains, that is included in
>> mangled name, so we also need to instantiate and export it.
>>
>> The new members added by C++23 are still not exported, and so the
>> explicit instantiation declarations are still disabled for C++23.
>>
>> libstdc++-v3/ChangeLog:
>>
>> * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make string exports
>> less greedy.
>> (GLIBCXX_3.4.26): Export basic_string default constructor and
>> starts_with and ends_with members.
>> * include/bits/basic_string.h: Update __cpluplus checks for C++20.
>> * include/bits/cow_string.h: Likewise.
>> * include/bits/basic_string.tcc: Declare explicit instantiations
>> for C++20 as well as earlier dialects.
>> * src/c++20/Makefile.am: Add cow-string-inst.cc and
>> string-inst.cc source files.
>> * src/c++20/Makefile.in: Regenerate.
>> * src/c++20/string-inst.cc: New file defining explicit
>> instantiations for basic_string default constructor and
>> starts_with,
>> ends_with methods added in C++20
>> * src/c++20/cow-string-inst.cc: Version of above for cow-stings.
>>
>> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
>> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
>> ---
>> v2 updates the years in copyright and standard reference,
>> as suggested.
>>
>> Tested after Jakub's fix for PR124754 on x86_64-linux,
>> and all test passed. Same for test -O0.
>> OK for trunk?
>>
>
> OK, thanks
this patch broke Solaris bootstrap:
ld: fatal: libstdc++-symbols.ver-sun: 3753: symbol '_ZNKSs11_M_disjunctEPKc': symbol version conflict
ld: fatal: libstdc++-symbols.ver-sun: 3765: symbol '_ZNKSbIwSt11char_traitsIwESaIwEE11_M_disjunctEPKw': symbol version conflict
Both symbols now match GLIBCXX_3.4 and GLIBCXX_3.4.5.
Rainer
I think I made an mistake splitting the pattern:
- _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][0-9][a-z]*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
Note that for 11 I am now matching _M_disjunt. Looking at
the baseline_symbols.txt file,
this seem to be only name with 11 characters, so the pattern seem
unnecessary.
Could you check if the following patch fixes it for you?
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver
b/libstdc++-v3/config/abi/pre/gnu.ver
index 2ff2aa02383..433b36af965 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -270,7 +270,6 @@ GLIBCXX_3.4 {
_ZNKSs[5-9][a-b]*;
_ZNKSs[0-8][d-e]*;
_ZNKSs[0-9][g-z]*;
- _ZNKSs11_[MS]_*;
_ZNKSs1[2-8][a-z]*;
_ZNKSs[2-9][0-9][a-z]*;
_ZNKSs4find*;
@@ -343,7 +342,6 @@ GLIBCXX_3.4 {
_ZNKSbIwSt11char_traitsIwESaIwEE[5-9][a-b]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[0-8][d-e]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[0-9][g-z]*;
- _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
_ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[abd-z]*;
@@ -1815,7 +1813,6 @@ GLIBCXX_3.4.21 {
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev;
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]I[PN]*;
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[Daip]*;
-
_ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11_[MS]_*;
_ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE1[2-9]*;
_ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[2-8]*;
_ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEixE[jmy];
On Wed, Apr 8, 2026 at 7:41 PM Rainer Orth <ro@cebitec.uni-bielefeld.de>
wrote:
> Hi Jonathan,
>
> > On Sat, 4 Apr 2026, 17:26 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
> >
> >> The C++20 standard added new starts_with and ends_with members to
> >> std::basic_string, which were not previously instantiated in the
> library.
> >> This meant that the extern template declarations had to be disabled for
> >> C++20 mode. With this patch the new members are instantiated in the
> >> library and so the explicit instantiation declarations can be used for
> >> C++20.
> >>
> >> Furthermore, basic_string default constructor is now constrained with
> >> is_default_constructible_v<_Alloc> constrains, that is included in
> >> mangled name, so we also need to instantiate and export it.
> >>
> >> The new members added by C++23 are still not exported, and so the
> >> explicit instantiation declarations are still disabled for C++23.
> >>
> >> libstdc++-v3/ChangeLog:
> >>
> >> * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make string exports
> >> less greedy.
> >> (GLIBCXX_3.4.26): Export basic_string default constructor and
> >> starts_with and ends_with members.
> >> * include/bits/basic_string.h: Update __cpluplus checks for
> C++20.
> >> * include/bits/cow_string.h: Likewise.
> >> * include/bits/basic_string.tcc: Declare explicit instantiations
> >> for C++20 as well as earlier dialects.
> >> * src/c++20/Makefile.am: Add cow-string-inst.cc and
> >> string-inst.cc source files.
> >> * src/c++20/Makefile.in: Regenerate.
> >> * src/c++20/string-inst.cc: New file defining explicit
> >> instantiations for basic_string default constructor and
> >> starts_with,
> >> ends_with methods added in C++20
> >> * src/c++20/cow-string-inst.cc: Version of above for cow-stings.
> >>
> >> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
> >> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
> >> ---
> >> v2 updates the years in copyright and standard reference,
> >> as suggested.
> >>
> >> Tested after Jakub's fix for PR124754 on x86_64-linux,
> >> and all test passed. Same for test -O0.
> >> OK for trunk?
> >>
> >
> > OK, thanks
>
> this patch broke Solaris bootstrap:
>
> ld: fatal: libstdc++-symbols.ver-sun: 3753: symbol
> '_ZNKSs11_M_disjunctEPKc': symbol version conflict
> ld: fatal: libstdc++-symbols.ver-sun: 3765: symbol
> '_ZNKSbIwSt11char_traitsIwESaIwEE11_M_disjunctEPKw': symbol version conflict
>
> Both symbols now match GLIBCXX_3.4 and GLIBCXX_3.4.5.
>
> Rainer
>
> --
>
> -----------------------------------------------------------------------------
> Rainer Orth, Center for Biotechnology, Bielefeld University
>
>
On Wed, Apr 8, 2026 at 8:02 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
> I think I made an mistake splitting the pattern:
> - _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][0-9][a-z]*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
> + _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
> Note that for 11 I am now matching _M_disjunt. Looking at
> the baseline_symbols.txt file,
> this seem to be only name with 11 characters, so the pattern seem
> unnecessary.
>
> Could you check if the following patch fixes it for you?
> diff --git a/libstdc++-v3/config/abi/pre/gnu.ver
> b/libstdc++-v3/config/abi/pre/gnu.ver
> index 2ff2aa02383..433b36af965 100644
> --- a/libstdc++-v3/config/abi/pre/gnu.ver
> +++ b/libstdc++-v3/config/abi/pre/gnu.ver
> @@ -270,7 +270,6 @@ GLIBCXX_3.4 {
> _ZNKSs[5-9][a-b]*;
> _ZNKSs[0-8][d-e]*;
> _ZNKSs[0-9][g-z]*;
> - _ZNKSs11_[MS]_*;
> _ZNKSs1[2-8][a-z]*;
> _ZNKSs[2-9][0-9][a-z]*;
> _ZNKSs4find*;
> @@ -343,7 +342,6 @@ GLIBCXX_3.4 {
> _ZNKSbIwSt11char_traitsIwESaIwEE[5-9][a-b]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[0-8][d-e]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][g-z]*;
> - _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
> _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
> _ZNKSbIwSt11char_traitsIwESaIwEE[abd-z]*;
> @@ -1815,7 +1813,6 @@ GLIBCXX_3.4.21 {
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev;
>
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]I[PN]*;
> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[Daip]*;
> -
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11_[MS]_*;
>
Please ignore this last change, and test only the two above.
>
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE1[2-9]*;
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[2-8]*;
>
> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEixE[jmy];
>
>
>
>
> On Wed, Apr 8, 2026 at 7:41 PM Rainer Orth <ro@cebitec.uni-bielefeld.de>
> wrote:
>
>> Hi Jonathan,
>>
>> > On Sat, 4 Apr 2026, 17:26 Tomasz Kamiński, <tkaminsk@redhat.com> wrote:
>> >
>> >> The C++20 standard added new starts_with and ends_with members to
>> >> std::basic_string, which were not previously instantiated in the
>> library.
>> >> This meant that the extern template declarations had to be disabled for
>> >> C++20 mode. With this patch the new members are instantiated in the
>> >> library and so the explicit instantiation declarations can be used for
>> >> C++20.
>> >>
>> >> Furthermore, basic_string default constructor is now constrained with
>> >> is_default_constructible_v<_Alloc> constrains, that is included in
>> >> mangled name, so we also need to instantiate and export it.
>> >>
>> >> The new members added by C++23 are still not exported, and so the
>> >> explicit instantiation declarations are still disabled for C++23.
>> >>
>> >> libstdc++-v3/ChangeLog:
>> >>
>> >> * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make string exports
>> >> less greedy.
>> >> (GLIBCXX_3.4.26): Export basic_string default constructor and
>> >> starts_with and ends_with members.
>> >> * include/bits/basic_string.h: Update __cpluplus checks for
>> C++20.
>> >> * include/bits/cow_string.h: Likewise.
>> >> * include/bits/basic_string.tcc: Declare explicit
>> instantiations
>> >> for C++20 as well as earlier dialects.
>> >> * src/c++20/Makefile.am: Add cow-string-inst.cc and
>> >> string-inst.cc source files.
>> >> * src/c++20/Makefile.in: Regenerate.
>> >> * src/c++20/string-inst.cc: New file defining explicit
>> >> instantiations for basic_string default constructor and
>> >> starts_with,
>> >> ends_with methods added in C++20
>> >> * src/c++20/cow-string-inst.cc: Version of above for
>> cow-stings.
>> >>
>> >> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
>> >> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
>> >> ---
>> >> v2 updates the years in copyright and standard reference,
>> >> as suggested.
>> >>
>> >> Tested after Jakub's fix for PR124754 on x86_64-linux,
>> >> and all test passed. Same for test -O0.
>> >> OK for trunk?
>> >>
>> >
>> > OK, thanks
>>
>> this patch broke Solaris bootstrap:
>>
>> ld: fatal: libstdc++-symbols.ver-sun: 3753: symbol
>> '_ZNKSs11_M_disjunctEPKc': symbol version conflict
>> ld: fatal: libstdc++-symbols.ver-sun: 3765: symbol
>> '_ZNKSbIwSt11char_traitsIwESaIwEE11_M_disjunctEPKw': symbol version conflict
>>
>> Both symbols now match GLIBCXX_3.4 and GLIBCXX_3.4.5.
>>
>> Rainer
>>
>> --
>>
>> -----------------------------------------------------------------------------
>> Rainer Orth, Center for Biotechnology, Bielefeld University
>>
>>
Hi Tomasz,
> On Wed, Apr 8, 2026 at 8:02 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>> I think I made an mistake splitting the pattern:
>> - _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][0-9][a-z]*;
>> + _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
>> + _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
>> + _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
>> Note that for 11 I am now matching _M_disjunt. Looking at
>> the baseline_symbols.txt file,
>> this seem to be only name with 11 characters, so the pattern seem
>> unnecessary.
>>
>> Could you check if the following patch fixes it for you?
>> diff --git a/libstdc++-v3/config/abi/pre/gnu.ver
>> b/libstdc++-v3/config/abi/pre/gnu.ver
>> index 2ff2aa02383..433b36af965 100644
>> --- a/libstdc++-v3/config/abi/pre/gnu.ver
>> +++ b/libstdc++-v3/config/abi/pre/gnu.ver
>> @@ -270,7 +270,6 @@ GLIBCXX_3.4 {
>> _ZNKSs[5-9][a-b]*;
>> _ZNKSs[0-8][d-e]*;
>> _ZNKSs[0-9][g-z]*;
>> - _ZNKSs11_[MS]_*;
>> _ZNKSs1[2-8][a-z]*;
>> _ZNKSs[2-9][0-9][a-z]*;
>> _ZNKSs4find*;
>> @@ -343,7 +342,6 @@ GLIBCXX_3.4 {
>> _ZNKSbIwSt11char_traitsIwESaIwEE[5-9][a-b]*;
>> _ZNKSbIwSt11char_traitsIwESaIwEE[0-8][d-e]*;
>> _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][g-z]*;
>> - _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
>> _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
>> _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
>> _ZNKSbIwSt11char_traitsIwESaIwEE[abd-z]*;
>> @@ -1815,7 +1813,6 @@ GLIBCXX_3.4.21 {
>> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev;
>>
>> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]I[PN]*;
>> _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[Daip]*;
>> -
>> _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11_[MS]_*;
>>
> Please ignore this last change, and test only the two above.
looks good: builds are in stage 2 now.
Thanks.
Rainer
Hi Tomasz,
>> Please ignore this last change, and test only the two above.
>
> looks good: builds are in stage 2 now.
while there were not Solaris-specific regressions, the original patch
caused this regression
+FAIL: g++.dg/lto/20091022-2 cp_lto_20091022-2_0.o assemble, -O3 -flto -Winline
+FAIL: g++.dg/lto/20091022-2 cp_lto_20091022-2_0.o-cp_lto_20091022-2_0.o link, -O3 -flto -Winline
In file included from i386-pc-solaris2.11/libstdc++-v3/include/string:58,
from /vol/gcc/src/hg/master/local/gcc/testsuite/g++.dg/lto/20091022-2_0.C:5:
In member function 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()',
inlined from 'main' at /vol/gcc/src/hg/master/local/gcc/testsuite/g++.dg/lto/20091022-2_0.C:12:1:
i386-pc-solaris2.11/libstdc++-v3/include/bits/basic_string.h:295:7: warning: inlining failed in call to 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose()': call is unlikely and code size would grow [-Winline]
i386-pc-solaris2.11/libstdc++-v3/include/bits/basic_string.h:920:19: note: called from here
apparently everywhere: seen on i386-pc-solaris2.11,
sparc-sun-solaris2.11, x86_64-pc-linux-gnu, and i686-pc-linux-gnu.
Rainer
On Thu, Apr 9, 2026 at 3:51 AM Rainer Orth <ro@cebitec.uni-bielefeld.de>
wrote:
> Hi Tomasz,
>
> >> Please ignore this last change, and test only the two above.
> >
> > looks good: builds are in stage 2 now.
>
> while there were not Solaris-specific regressions, the original patch
> caused this regression
>
> +FAIL: g++.dg/lto/20091022-2 cp_lto_20091022-2_0.o assemble, -O3 -flto
> -Winline
> +FAIL: g++.dg/lto/20091022-2 cp_lto_20091022-2_0.o-cp_lto_20091022-2_0.o
> link, -O3 -flto -Winline
>
> In file included from i386-pc-solaris2.11/libstdc++-v3/include/string:58,
> from
> /vol/gcc/src/hg/master/local/gcc/testsuite/g++.dg/lto/20091022-2_0.C:5:
> In member function 'std::__cxx11::basic_string<char,
> std::char_traits<char>, std::allocator<char> >::~basic_string()',
> inlined from 'main' at
> /vol/gcc/src/hg/master/local/gcc/testsuite/g++.dg/lto/20091022-2_0.C:12:1:
> i386-pc-solaris2.11/libstdc++-v3/include/bits/basic_string.h:295:7:
> warning: inlining failed in call to 'std::__cxx11::basic_string<char,
> std::char_traits<char>, std::allocator<char> >::_M_dispose()': call is
> unlikely and code size would grow [-Winline]
> i386-pc-solaris2.11/libstdc++-v3/include/bits/basic_string.h:920:19: note:
> called from here
I have created a bugzilla ticket for it
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124828.
>
> apparently everywhere: seen on i386-pc-solaris2.11,
> sparc-sun-solaris2.11, x86_64-pc-linux-gnu, and i686-pc-linux-gnu.
>
> Rainer
>
> --
>
> -----------------------------------------------------------------------------
> Rainer Orth, Center for Biotechnology, Bielefeld University
>
>
@@ -268,9 +268,11 @@ GLIBCXX_3.4 {
_ZNSspLE[PRc]*;
_ZNKSs[0-3][a-b]*;
_ZNKSs[5-9][a-b]*;
- _ZNKSs[0-9][d-e]*;
+ _ZNKSs[0-8][d-e]*;
_ZNKSs[0-9][g-z]*;
- _ZNKSs[0-9][0-9][a-z]*;
+ _ZNKSs11_[MS]_*;
+ _ZNKSs1[2-8][a-z]*;
+ _ZNKSs[2-9][0-9][a-z]*;
_ZNKSs4find*;
_ZNKSs[abd-z]*;
_ZNKSs4_Rep12_M_is_leakedEv;
@@ -339,9 +341,11 @@ GLIBCXX_3.4 {
_ZNSbIwSt11char_traitsIwESaIwEEpLE[PRw]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[0-3][a-b]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[5-9][a-b]*;
- _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][d-e]*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE[0-8][d-e]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[0-9][g-z]*;
- _ZNKSbIwSt11char_traitsIwESaIwEE[0-9][0-9][a-z]*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE11_[MS]_*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE1[2-8][a-z]*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE[2-9][0-9][a-z]*;
_ZNKSbIwSt11char_traitsIwESaIwEE[abd-z]*;
_ZNKSbIwSt11char_traitsIwESaIwEE4find*;
_ZNKSbIwSt11char_traitsIwESaIwEE4_Rep12_M_is_leakedEv;
@@ -1811,7 +1815,9 @@ GLIBCXX_3.4.21 {
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]Ev;
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]I[PN]*;
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[Daip]*;
- _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[1-9]*;
+ _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11_[MS]_*;
+ _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE1[2-9]*;
+ _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE[2-8]*;
_ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEixE[jmy];
# operator+ for ABI-tagged std::basic_string
@@ -2587,6 +2593,21 @@ GLIBCXX_3.4.35 {
_ZNSt12__cow_stringaSEOS_;
_ZNKSt12__cow_string5c_strEv;
+ # basic_string::starts_with
+ _ZNKSs11starts_with*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE11starts_with*;
+ _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE11starts_with*;
+
+ # basic_string::ends_with
+ _ZNKSs9ends_with*;
+ _ZNKSbIwSt11char_traitsIwESaIwEE9ends_with*;
+ _ZNKSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE9ends_with*;
+
+ # basic_string::basic_string() noexcept is_default_constructible<Allocator>;
+ _ZNSsC[12]EvQ26is_default_constructible_vIT1_E;
+ _ZNSbIwSt11char_traitsIwESaIwEEC[12]EvQ26is_default_constructible_vIT1_E;
+ _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[1-2]EvQ26is_default_constructible_vIT1_E;
+
#if defined (_WIN32) && !defined (__CYGWIN__)
_ZSt19__get_once_callablev;
_ZSt15__get_once_callv;
@@ -1331,7 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/**
* Equivalent to shrink_to_fit().
*/
-#if __cplusplus > 201703L
+#if __cplusplus >= 202002L
[[deprecated("use shrink_to_fit() instead")]]
#endif
_GLIBCXX20_CONSTEXPR
@@ -1031,12 +1031,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
#if _GLIBCXX_EXTERN_TEMPLATE
- // The explicit instantiation definitions in src/c++11/string-inst.cc and
- // src/c++17/string-inst.cc only instantiate the members required for C++17
- // and earlier standards (so not C++20's starts_with and ends_with).
- // Suppress the explicit instantiation declarations for C++20, so C++20
+ // The explicit instantiation definitions in src/c++11/string-inst.cc,
+ // src/c++17/string-inst.cc and src/c++20/string-inst.cc only instantiate
+ // the members required for C++20 and earlier standards (so not C++23's
+ // contains).
+ // Suppress the explicit instantiation declarations for C++23, so C++23
// code will implicitly instantiate std::string and std::wstring as needed.
-# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
+# if __cplusplus <= 202002L && _GLIBCXX_EXTERN_TEMPLATE > 0
extern template class basic_string<char>;
# elif ! _GLIBCXX_USE_CXX11_ABI
// Still need to prevent implicit instantiation of the COW empty rep,
@@ -1044,7 +1045,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
extern template basic_string<char>::size_type
basic_string<char>::_Rep::_S_empty_rep_storage[];
# elif _GLIBCXX_EXTERN_TEMPLATE > 0
- // Export _M_replace_cold even for C++20.
+ // Export _M_replace_cold even for C++23.
extern template void
basic_string<char>::_M_replace_cold(char *, size_type, const char*,
const size_type, const size_type);
@@ -1064,13 +1065,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
getline(basic_istream<char>&, string&);
#ifdef _GLIBCXX_USE_WCHAR_T
-# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
+# if __cplusplus <= 202002L && _GLIBCXX_EXTERN_TEMPLATE > 0
extern template class basic_string<wchar_t>;
# elif ! _GLIBCXX_USE_CXX11_ABI
extern template basic_string<wchar_t>::size_type
basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
# elif _GLIBCXX_EXTERN_TEMPLATE > 0
- // Export _M_replace_cold even for C++20.
+ // Export _M_replace_cold even for C++23.
extern template void
basic_string<wchar_t>::_M_replace_cold(wchar_t*, size_type, const wchar_t*,
const size_type, const size_type);
@@ -1080,7 +1080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
reserve(size_type __res_arg);
/// Equivalent to shrink_to_fit().
-#if __cplusplus > 201703L
+#if __cplusplus >= 202002L
[[deprecated("use shrink_to_fit() instead")]]
#endif
void
@@ -3194,7 +3194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __r;
}
-#if __cplusplus > 201703L
+#if __cplusplus >= 202002L
bool
starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
{ return __sv_type(this->data(), this->size()).starts_with(__x); }
@@ -27,10 +27,19 @@ noinst_LTLIBRARIES = libc++20convenience.la
headers =
+if ENABLE_DUAL_ABI
+extra_string_inst_sources = cow-string-inst.cc
+else
+extra_string_inst_sources =
+endif
+
+
if ENABLE_EXTERN_TEMPLATE
# XTEMPLATE_FLAGS = -fno-implicit-templates
inst_sources = \
- sstream-inst.cc
+ sstream-inst.cc \
+ string-inst.cc \
+ $(extra_string_inst_sources)
else
# XTEMPLATE_FLAGS =
inst_sources =
@@ -40,6 +49,11 @@ sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc
vpath % $(top_srcdir)/src/c++20
+if ENABLE_DUAL_ABI
+# These files should be rebuilt if the .cc prerequisite changes.
+cow-string-inst.lo cow-string-inst.o: string-inst.cc
+endif
+
if USE_STATIC_TZDATA
tzdata.zi.h: $(top_srcdir)/src/c++20/tzdata.zi
echo 'static const char tzdata_chars[] = R"__libstdcxx__(' > $@.tmp
@@ -124,9 +124,11 @@ CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libc__20convenience_la_LIBADD =
am__objects_1 = tzdb.lo format.lo atomic.lo clock.lo syncbuf.lo
-@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = sstream-inst.lo
+@ENABLE_DUAL_ABI_TRUE@am__objects_2 = cow-string-inst.lo
+@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_3 = sstream-inst.lo \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo $(am__objects_2)
@GLIBCXX_HOSTED_TRUE@am_libc__20convenience_la_OBJECTS = \
-@GLIBCXX_HOSTED_TRUE@ $(am__objects_1) $(am__objects_2)
+@GLIBCXX_HOSTED_TRUE@ $(am__objects_1) $(am__objects_3)
libc__20convenience_la_OBJECTS = $(am_libc__20convenience_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -428,12 +430,16 @@ AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS)
# Convenience library for C++20 runtime.
noinst_LTLIBRARIES = libc++20convenience.la
headers =
+@ENABLE_DUAL_ABI_FALSE@extra_string_inst_sources =
+@ENABLE_DUAL_ABI_TRUE@extra_string_inst_sources = cow-string-inst.cc
# XTEMPLATE_FLAGS =
@ENABLE_EXTERN_TEMPLATE_FALSE@inst_sources =
# XTEMPLATE_FLAGS = -fno-implicit-templates
@ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \
-@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc
+@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.cc \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ $(extra_string_inst_sources)
sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc
@GLIBCXX_HOSTED_FALSE@libc__20convenience_la_SOURCES =
@@ -747,6 +753,9 @@ uninstall-am:
vpath % $(top_srcdir)/src/c++20
+# These files should be rebuilt if the .cc prerequisite changes.
+@ENABLE_DUAL_ABI_TRUE@cow-string-inst.lo cow-string-inst.o: string-inst.cc
+
@USE_STATIC_TZDATA_TRUE@tzdata.zi.h: $(top_srcdir)/src/c++20/tzdata.zi
@USE_STATIC_TZDATA_TRUE@ echo 'static const char tzdata_chars[] = R"__libstdcxx__(' > $@.tmp
@USE_STATIC_TZDATA_TRUE@ cat $^ >> $@.tmp
new file mode 100644
@@ -0,0 +1,34 @@
+// Reference-counted COW string instantiations for C++20 -*- C++ -*-
+
+// Copyright (C) 2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882:2020 21 Strings library
+//
+
+#define _GLIBCXX_USE_CXX11_ABI 0
+#include "string-inst.cc"
+
+#if ! _GLIBCXX_USE_DUAL_ABI
+# error This file should not be compiled for this configuration.
+#endif
new file mode 100644
@@ -0,0 +1,59 @@
+// string instantiations for C++20 -*- C++ -*-
+
+// Copyright (C) 2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882:2020 21 Strings library
+//
+
+#ifndef _GLIBCXX_USE_CXX11_ABI
+// Instantiations in this file use the new SSO std::string ABI unless included
+// by another file which defines _GLIBCXX_USE_CXX11_ABI=0.
+# define _GLIBCXX_USE_CXX11_ABI 1
+#endif
+
+#include <string>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+template basic_string<char>::basic_string() noexcept;
+template bool basic_string<char>::starts_with(string_view) const noexcept;
+template bool basic_string<char>::starts_with(char) const noexcept;
+template bool basic_string<char>::starts_with(const char*) const noexcept;
+template bool basic_string<char>::ends_with(string_view) const noexcept;
+template bool basic_string<char>::ends_with(char) const noexcept;
+template bool basic_string<char>::ends_with(const char*) const noexcept;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+template basic_string<wchar_t>::basic_string() noexcept;
+template bool basic_string<wchar_t>::starts_with(wstring_view) const noexcept;
+template bool basic_string<wchar_t>::starts_with(wchar_t) const noexcept;
+template bool basic_string<wchar_t>::starts_with(const wchar_t*) const noexcept;
+template bool basic_string<wchar_t>::ends_with(wstring_view) const noexcept;
+template bool basic_string<wchar_t>::ends_with(wchar_t) const noexcept;
+template bool basic_string<wchar_t>::ends_with(const wchar_t*) const noexcept;
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std