https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123991

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
      Known to fail|                            |13.4.0, 14.3.0, 15.2.0,
                   |                            |16.0, 7.3.0, 8.1.0
            Summary|std::string::compare        |[13/14/15/16 Regression]
                   |crashes instead of throwing |std::string::compare
                   |                            |crashes instead of throwing
      Known to work|                            |7.2.0

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The noexcept was added by r8-2892-gdf66af3b1edaf4

The same conditional noexcept was added here:

+      template<typename _Tp>
+       _If_sv<_Tp, int>
+       compare(const _Tp& __svt) const
+       noexcept(is_same<_Tp, __sv_type>::value)
+       {

And in this case it's correct. As the standard says:

 -?- Throws: Nothing unless the initialization of sv throws an exception. 

So when _Tp is already string_view, we know that initializing a string_view
from __svt will not throw.

But for the topic of this bug report:

+      template<typename _Tp>
+       _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);
+       }

Adding the conditional noexcept was wrong, because the substr can throw even if
initializing __sv cannot throw.

This is a regression, because GCC 7.2.0 was correct (and then I backported the
gcc-8 change to the gcc-7 branch as bb85d61e6bfba).

The same problem exists on this overload:

      template<typename _Tp>
        _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
        _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)
            .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
        }

Reply via email to