From: Jonathan Wakely Date: Mon, 9 Feb 2026 10:48:44 +0000 (+0000) Subject: libstdc++: Fix incorrect noexcept on string::compare overloads [PR123991] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0912dfcd1e901d7dc1ff5e10528eefe3f3ff7b22;p=thirdparty%2Fgcc.git libstdc++: Fix incorrect noexcept on string::compare overloads [PR123991] These compare overloads throw when the pos index is out of range, not only when the const T& parameter throws on conversion to string_view. Remove the incorrect conditional noexcept-specifier from the two overloads that can throw. libstdc++-v3/ChangeLog: PR libstdc++/123991 * include/bits/basic_string.h (compare(size_type, size_type, T)): Remove noexcept-specifier. (compare(size_type, size_type, T, size_type, size_type)): Likewise. * include/bits/cow_string.h (compare(size_type, size_type, T)): Remove noexcept-specifier. (compare(size_type, size_type, T, size_type, size_type)): Likewise. * testsuite/21_strings/basic_string/operations/compare/char/123991.cc: New test. * testsuite/21_strings/basic_string/operations/compare/wchar_t/123991.cc: New test. Reviewed-by: Nathan Myers --- diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 0602b0dcac8..cd6f312f1bd 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3524,7 +3524,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos, size_type __n, const _Tp& __svt) const - noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this).substr(__pos, __n).compare(__sv); @@ -3545,7 +3544,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const - noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this) diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index 36c19fabfc5..6cf00224372 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -2998,7 +2998,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _If_sv<_Tp, int> compare(size_type __pos, size_type __n, const _Tp& __svt) const - noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this).substr(__pos, __n).compare(__sv); @@ -3018,7 +3017,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const - noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/123991.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/123991.cc new file mode 100644 index 00000000000..53ef2d4606c --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/char/123991.cc @@ -0,0 +1,56 @@ +// { dg-do run { target c++17 } } + +// Bug 123991 - std::string::compare crashes instead of throwing + +#include +#include +#include +#include + +void +test_compare_3arg() +{ + std::string_view sv; + std::string s; + static_assert( ! noexcept(s.compare(0, 0, sv)) ); +#ifdef __cpp_exceptions + try + { + (void) s.compare(1, 0, sv); + VERIFY(false); + } + catch (const std::out_of_range&) + { } +#endif +} + +void +test_compare_5arg() +{ + std::string_view sv; + std::string s; + static_assert( ! noexcept(s.compare(0, 0, sv, 0, 0)) ); +#ifdef __cpp_exceptions + try + { + (void) s.compare(1, 0, sv, 0, 0); + VERIFY(false); + } + catch (const std::out_of_range&) + { } + + try + { + (void) s.compare(0, 0, sv, 1, 0); + VERIFY(false); + } + catch (const std::out_of_range&) + { } +#endif +} + +int main() +{ + test_compare_3arg(); + test_compare_5arg(); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/123991.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/123991.cc new file mode 100644 index 00000000000..c4188bbff8b --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/compare/wchar_t/123991.cc @@ -0,0 +1,56 @@ +// { dg-do run { target c++17 } } + +// Bug 123991 - std::string::compare crashes instead of throwing + +#include +#include +#include +#include + +void +test_compare_3arg() +{ + std::wstring_view sv; + std::wstring s; + static_assert( ! noexcept(s.compare(0, 0, sv)) ); +#ifdef __cpp_exceptions + try + { + (void) s.compare(1, 0, sv); + VERIFY(false); + } + catch (const std::out_of_range&) + { } +#endif +} + +void +test_compare_5arg() +{ + std::wstring_view sv; + std::wstring s; + static_assert( ! noexcept(s.compare(0, 0, sv, 0, 0)) ); +#ifdef __cpp_exceptions + try + { + (void) s.compare(1, 0, sv, 0, 0); + VERIFY(false); + } + catch (const std::out_of_range&) + { } + + try + { + (void) s.compare(0, 0, sv, 1, 0); + VERIFY(false); + } + catch (const std::out_of_range&) + { } +#endif +} + +int main() +{ + test_compare_3arg(); + test_compare_5arg(); +}