Some more C++20 changes from P1614R2, "The Mothership has Landed".

This adds three-way comparison support to std::char_traits,
std::basic_string, std::basic_string_view, and std::sub_match.

        * include/bits/basic_string.h (basic_string): Define operator<=> and
        remove redundant comparison operators for C++20.
        * include/bits/char_traits.h (__gnu_cxx::char_traits, char_traits):
        Add comparison_category members.
        (__detail::__char_traits_cmp_cat): New helper to get comparison
        category from char traits class.
        * include/bits/regex.h (regex_traits::_RegexMask::operator!=): Do not
        define for C++20.
        (sub_match): Define operator<=> and remove redundant comparison
        operators for C++20.
        (match_results): Remove redundant operator!= for C++20.
        * include/std/string_view (basic_string_view): Define operator<=> and
        remove redundant comparison operators for C++20.
        * testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc: New
        test.
        * testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc:
        New test.
        * testsuite/21_strings/basic_string_view/operations/copy/char/
        constexpr.cc: Initialize variable.
        * testsuite/21_strings/basic_string_view/operations/copy/wchar_t/
        constexpr.cc: Likewise.
        * testsuite/21_strings/basic_string_view/operators/char/2.cc: Add
        dg-do directive and remove comments showing incorrect signatures.
        * testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc:
        Likewise.
        * testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc:
        New test.
        * testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc:
        New test.
        * testsuite/28_regex/sub_match/compare_c++20.cc: New test.

Tested powerpc64le-linux, committed to master.


commit 875d6cb3b4919b58ae5e6313db715bc4dd3ddd6c
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Fri Apr 17 16:24:49 2020 +0100

    libstdc++: Add comparison operators for string and regex types
    
    Some more C++20 changes from P1614R2, "The Mothership has Landed".
    
    This adds three-way comparison support to std::char_traits,
    std::basic_string, std::basic_string_view, and std::sub_match.
    
            * include/bits/basic_string.h (basic_string): Define operator<=> and
            remove redundant comparison operators for C++20.
            * include/bits/char_traits.h (__gnu_cxx::char_traits, char_traits):
            Add comparison_category members.
            (__detail::__char_traits_cmp_cat): New helper to get comparison
            category from char traits class.
            * include/bits/regex.h (regex_traits::_RegexMask::operator!=): Do 
not
            define for C++20.
            (sub_match): Define operator<=> and remove redundant comparison
            operators for C++20.
            (match_results): Remove redundant operator!= for C++20.
            * include/std/string_view (basic_string_view): Define operator<=> 
and
            remove redundant comparison operators for C++20.
            * testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc: New
            test.
            * testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc:
            New test.
            * testsuite/21_strings/basic_string_view/operations/copy/char/
            constexpr.cc: Initialize variable.
            * testsuite/21_strings/basic_string_view/operations/copy/wchar_t/
            constexpr.cc: Likewise.
            * testsuite/21_strings/basic_string_view/operators/char/2.cc: Add
            dg-do directive and remove comments showing incorrect signatures.
            * testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc:
            Likewise.
            * 
testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc:
            New test.
            * 
testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc:
            New test.
            * testsuite/28_regex/sub_match/compare_c++20.cc: New test.

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 0374f8e6805..bc0c256b65e 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -6164,18 +6164,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
              && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
                                                    __lhs.size())); }
 
-  /**
-   *  @brief  Test equivalence of C string and string.
-   *  @param __lhs  C string.
-   *  @param __rhs  String.
-   *  @return  True if @a __rhs.compare(@a __lhs) == 0.  False otherwise.
-   */
-  template<typename _CharT, typename _Traits, typename _Alloc>
-    inline bool
-    operator==(const _CharT* __lhs,
-              const basic_string<_CharT, _Traits, _Alloc>& __rhs)
-    { return __rhs.compare(__lhs) == 0; }
-
   /**
    *  @brief  Test equivalence of string and C string.
    *  @param __lhs  String.
@@ -6188,6 +6176,47 @@ _GLIBCXX_END_NAMESPACE_CXX11
               const _CharT* __rhs)
     { return __lhs.compare(__rhs) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  /**
+   *  @brief  Three-way comparison of a string and a C string.
+   *  @param __lhs  A string.
+   *  @param __rhs  A null-terminated string.
+   *  @return  A value indicating whether `__lhs` is less than, equal to,
+   *          greater than, or incomparable with `__rhs`.
+   */
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    inline auto
+    operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
+               const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept
+    -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
+    { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
+
+  /**
+   *  @brief  Three-way comparison of a string and a C string.
+   *  @param __lhs  A string.
+   *  @param __rhs  A null-terminated string.
+   *  @return  A value indicating whether `__lhs` is less than, equal to,
+   *          greater than, or incomparable with `__rhs`.
+   */
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    inline auto
+    operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
+               const _CharT* __rhs) noexcept
+    -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
+    { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
+#else
+  /**
+   *  @brief  Test equivalence of C string and string.
+   *  @param __lhs  C string.
+   *  @param __rhs  String.
+   *  @return  True if @a __rhs.compare(@a __lhs) == 0.  False otherwise.
+   */
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    inline bool
+    operator==(const _CharT* __lhs,
+              const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    { return __rhs.compare(__lhs) == 0; }
+
   // operator !=
   /**
    *  @brief  Test difference of two strings.
@@ -6377,6 +6406,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     operator>=(const _CharT* __lhs,
             const basic_string<_CharT, _Traits, _Alloc>& __rhs)
     { return __rhs.compare(__lhs) <= 0; }
+#endif // three-way comparison
 
   /**
    *  @brief  Swap contents of two strings.
diff --git a/libstdc++-v3/include/bits/char_traits.h 
b/libstdc++-v3/include/bits/char_traits.h
index 65031d3ac83..c6da184e4bd 100644
--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -39,6 +39,9 @@
 #include <bits/stl_algobase.h>  // std::copy, std::fill_n
 #include <bits/postypes.h>      // For streampos
 #include <cwchar>               // For WEOF, wmemmove, wmemset, etc.
+#if __cplusplus > 201703L
+# include <compare>
+#endif
 
 #ifndef _GLIBCXX_ALWAYS_INLINE
 # define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
@@ -91,6 +94,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef typename _Char_types<_CharT>::pos_type    pos_type;
       typedef typename _Char_types<_CharT>::off_type    off_type;
       typedef typename _Char_types<_CharT>::state_type  state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = std::strong_ordering;
+#endif
 
       static _GLIBCXX14_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2)
@@ -307,6 +313,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef streampos         pos_type;
       typedef streamoff         off_type;
       typedef mbstate_t         state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = strong_ordering;
+#endif
 
       static _GLIBCXX17_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
@@ -432,6 +441,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef streamoff         off_type;
       typedef wstreampos        pos_type;
       typedef mbstate_t         state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = strong_ordering;
+#endif
 
       static _GLIBCXX17_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
@@ -550,6 +562,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef u8streampos       pos_type;
       typedef streamoff         off_type;
       typedef mbstate_t         state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = strong_ordering;
+#endif
 
       static _GLIBCXX17_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
@@ -687,6 +702,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef streamoff         off_type;
       typedef u16streampos      pos_type;
       typedef mbstate_t         state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = strong_ordering;
+#endif
 
       static _GLIBCXX17_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2) noexcept
@@ -798,6 +816,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef streamoff         off_type;
       typedef u32streampos      pos_type;
       typedef mbstate_t         state_type;
+#if __cpp_lib_three_way_comparison
+      using comparison_category = strong_ordering;
+#endif
 
       static _GLIBCXX17_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2) noexcept
@@ -895,6 +916,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return eq_int_type(__c, eof()) ? 0 : __c; }
     };
 
+#if __cpp_lib_three_way_comparison
+  namespace __detail
+  {
+    template<typename _ChTraits>
+      constexpr auto
+      __char_traits_cmp_cat(int __cmp) noexcept
+      {
+       if constexpr (requires { typename _ChTraits::comparison_category; })
+         {
+           using _Cat = typename _ChTraits::comparison_category;
+           static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
+           return static_cast<_Cat>(__cmp <=> 0);
+         }
+       else
+         return static_cast<weak_ordering>(__cmp <=> 0);
+      }
+  } // namespace __detail
+#endif // C++20
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/include/bits/regex.h 
b/libstdc++-v3/include/bits/regex.h
index dcae83eea4e..6db05889e8c 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -142,11 +142,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
                     && _M_base == __other._M_base;
          }
 
+#if __cpp_impl_three_way_comparison < 201907L
          constexpr bool
          operator!=(_RegexMask __other) const
          { return !((*this) == __other); }
-
+#endif
        };
+
     public:
       typedef _RegexMask char_class_type;
 
@@ -1033,6 +1035,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator==(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& 
__rhs)
     { return __lhs.compare(__rhs) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  /**
+   * @brief Three-way comparison of two regular expression submatches.
+   * @param __lhs First regular expression submatch.
+   * @param __rhs Second regular expression submatch.
+   * @returns A value indicating whether `__lhs` is less than, equal to,
+   *         greater than, or incomparable with `__rhs`.
+   */
+  template<typename _BiIter>
+    inline auto
+    operator<=>(const sub_match<_BiIter>& __lhs,
+               const sub_match<_BiIter>& __rhs)
+    noexcept(__detail::__is_contiguous_iter<_BiIter>::value)
+    {
+      using _Tr = char_traits<typename iterator_traits<_BiIter>::value_type>;
+      return __detail::__char_traits_cmp_cat<_Tr>(__lhs.compare(__rhs));
+    }
+#else
   /**
    * @brief Tests the inequivalence of two regular expression submatches.
    * @param __lhs First regular expression submatch.
@@ -1087,6 +1107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     inline bool
     operator>(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
     { return __lhs.compare(__rhs) > 0; }
+#endif // three-way comparison
 
   /// @cond undocumented
 
@@ -1097,6 +1118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
                              _Ch_traits, _Ch_alloc>;
   /// @endcond
 
+#if ! __cpp_lib_three_way_comparison
   /**
    * @brief Tests the equivalence of a string and a regular expression
    *        submatch.
@@ -1170,6 +1192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator<=(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& 
__lhs,
               const sub_match<_Bi_iter>& __rhs)
     { return !(__rhs < __lhs); }
+#endif // three-way comparison
 
   /**
    * @brief Tests the equivalence of a regular expression submatch and a
@@ -1184,6 +1207,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
               const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
     { return __lhs._M_compare(__rhs.data(), __rhs.size()) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  /**
+   * @brief Three-way comparison of a regular expression submatch and a string.
+   * @param __lhs A regular expression submatch.
+   * @param __rhs A string.
+   * @returns A value indicating whether `__lhs` is less than, equal to,
+   *         greater than, or incomparable with `__rhs`.
+   */
+  template<typename _Bi_iter, typename _Ch_traits, typename _Alloc>
+    inline auto
+    operator<=>(const sub_match<_Bi_iter>& __lhs,
+               const __sub_match_string<_Bi_iter, _Ch_traits, _Alloc>& __rhs)
+    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+    {
+      return __detail::__char_traits_cmp_cat<_Ch_traits>(
+         __lhs._M_compare(__rhs.data(), __rhs.size()));
+    }
+#else
   /**
    * @brief Tests the inequivalence of a regular expression submatch and a
    *        string.
@@ -1318,6 +1359,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator<=(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
               const sub_match<_Bi_iter>& __rhs)
     { return !(__rhs < __lhs); }
+#endif // three-way comparison
 
   /**
    * @brief Tests the equivalence of a regular expression submatch and a C
@@ -1332,6 +1374,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
               typename iterator_traits<_Bi_iter>::value_type const* __rhs)
     { return __lhs.compare(__rhs) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  /**
+   * @brief Three-way comparison of a regular expression submatch and a C
+   *       string.
+   * @param __lhs A regular expression submatch.
+   * @param __rhs A null-terminated string.
+   * @returns A value indicating whether `__lhs` is less than, equal to,
+   *         greater than, or incomparable with `__rhs`.
+   */
+  template<typename _Bi_iter>
+    inline auto
+    operator<=>(const sub_match<_Bi_iter>& __lhs,
+               typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+    {
+      using _Tr = char_traits<typename iterator_traits<_Bi_iter>::value_type>;
+      return __detail::__char_traits_cmp_cat<_Tr>(__lhs.compare(__rhs));
+    }
+#else
   /**
    * @brief Tests the inequivalence of a regular expression submatch and a
    *        string.
@@ -1470,6 +1531,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator<=(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
               const sub_match<_Bi_iter>& __rhs)
     { return !(__rhs < __lhs); }
+#endif // three-way comparison
 
   /**
    * @brief Tests the equivalence of a regular expression submatch and a
@@ -1484,6 +1546,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
               typename iterator_traits<_Bi_iter>::value_type const& __rhs)
     { return __lhs._M_compare(std::__addressof(__rhs), 1) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  /**
+   * @brief Three-way comparison of a regular expression submatch and a
+   *       character.
+   * @param __lhs A regular expression submatch.
+   * @param __rhs A character.
+   * @returns A value indicating whether `__lhs` is less than, equal to,
+   *         greater than, or incomparable with `__rhs`.
+   */
+
+  template<typename _Bi_iter>
+    inline auto
+    operator<=>(const sub_match<_Bi_iter>& __lhs,
+               typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+    {
+      using _Tr = char_traits<typename iterator_traits<_Bi_iter>::value_type>;
+      return __detail::__char_traits_cmp_cat<_Tr>(
+         __lhs._M_compare(std::__addressof(__rhs), 1));
+    }
+#else
   /**
    * @brief Tests the inequivalence of a regular expression submatch and a
    *        character.
@@ -1548,6 +1631,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator<=(const sub_match<_Bi_iter>& __lhs,
               typename iterator_traits<_Bi_iter>::value_type const& __rhs)
     { return !(__rhs < __lhs); }
+#endif // three-way comparison
 
   /**
    * @brief Inserts a matched string into an output stream.
@@ -2031,6 +2115,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        && __m1.suffix() == __m2.suffix();
     }
 
+#if ! __cpp_lib_three_way_comparison
   /**
    * @brief Compares two match_results for inequality.
    * @returns true if the two objects do not refer to the same match,
@@ -2041,6 +2126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     operator!=(const match_results<_Bi_iter, _Alloc>& __m1,
               const match_results<_Bi_iter, _Alloc>& __m2) noexcept
     { return !(__m1 == __m2); }
+#endif
 
   // [7.10.6] match_results swap
   /**
diff --git a/libstdc++-v3/include/std/string_view 
b/libstdc++-v3/include/std/string_view
index ea1ccc9bb21..b5d8eab2f33 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -494,6 +494,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
+#if __cpp_lib_three_way_comparison
+  template<typename _CharT, typename _Traits>
+    constexpr auto
+    operator<=>(basic_string_view<_CharT, _Traits> __x,
+               basic_string_view<_CharT, _Traits> __y) noexcept
+    -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
+    { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); }
+
+  template<typename _CharT, typename _Traits>
+    constexpr auto
+    operator<=>(basic_string_view<_CharT, _Traits> __x,
+               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
+    noexcept
+    -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
+    { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); }
+#else
   template<typename _CharT, typename _Traits>
     constexpr bool
     operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
@@ -594,6 +610,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) >= 0; }
+#endif // three-way comparison
 
   // [string.view.io], Inserters and extractors
   template<typename _CharT, typename _Traits>
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc 
b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc
new file mode 100644
index 00000000000..b62d10bdb63
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc
@@ -0,0 +1,194 @@
+// Copyright (C) 2020 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// C++20 21.3.3.2 Non-member comparison functions [string.cmp]
+
+// operator==
+/*
+template<class charT, class traits, class Allocator>
+  constexpr bool
+  operator==(const basic_string<charT, traits, Allocator>& lhs,
+            const basic_string<charT, traits, Allocator>& rhs);
+
+template<class charT, class traits, class Allocator>
+  constexpr bool
+  operator==(const basic_string<charT, traits, Allocator>& lhs,
+            const charT* rhs);
+*/
+
+// operator<=>
+/*
+template<class charT, class traits, class Allocator>
+  constexpr [see below]
+  operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+             const basic_string<charT, traits, Allocator>& rhs);
+
+template<class charT, class traits, class Allocator>
+  constexpr [see below]
+  operator<=>(const basic_string<charT,traits,Allocator>& lhs,
+             const charT* rhs);
+*/
+
+#include <string>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::string  str_0("costa rica");
+  std::string  str_1("costa marbella");
+  std::string  str_2("cost");
+  std::string  str_3("costa ricans");
+  std::string        str_4;
+
+  str_4 = str_0;
+  //comparisons between string objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string object and string literal
+  VERIFY( !(str_0 == "costa marbella") );
+  VERIFY( !(str_0 == "cost") );
+  VERIFY( !(str_0 == "costa ricans") );
+  VERIFY( !("costa marbella" == str_0) );
+  VERIFY( !("cost" == str_0) );
+  VERIFY( !("costa ricans" == str_0) );
+  VERIFY( "costa rica" == str_0 );
+  VERIFY( str_0 == "costa rica" );
+
+  VERIFY( str_0 != "costa marbella" );
+  VERIFY( str_0 != "cost" );
+  VERIFY( str_0 != "costa ricans" );
+  VERIFY( "costa marbella" != str_0 );
+  VERIFY( "cost" != str_0 );
+  VERIFY( "costa ricans" != str_0 );
+  VERIFY( !("costa rica" != str_0) );
+  VERIFY( !(str_0 != "costa rica") );
+
+  VERIFY( str_0 > "costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > "cost" );
+  VERIFY( !(str_0 > "costa ricans") );
+  VERIFY( !("costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !("cost" > str_0) );
+  VERIFY( "costa ricans" > str_0 );
+  VERIFY( !("costa rica" > str_0) );
+  VERIFY( !(str_0 > "costa rica") );
+
+  VERIFY( !(str_0 < "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < "cost") );
+  VERIFY( str_0 < "costa ricans" );
+  VERIFY( "costa marbella" < str_0 );//true cuz m<r
+  VERIFY( "cost" < str_0 );
+  VERIFY( !("costa ricans" < str_0) );
+  VERIFY( !("costa rica" < str_0) );
+  VERIFY( !(str_0 < "costa rica") );
+
+  VERIFY( str_0 >= "costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= "cost" );
+  VERIFY( !(str_0 >= "costa ricans") );
+  VERIFY( !("costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !("cost" >= str_0) );
+  VERIFY( "costa ricans" >= str_0 );
+  VERIFY( "costa rica" >= str_0 );
+  VERIFY( str_0 >= "costa rica" );
+
+  VERIFY( !(str_0 <= "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= "cost") );
+  VERIFY( str_0 <= "costa ricans" );
+  VERIFY( "costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( "cost" <= str_0 );
+  VERIFY( !("costa ricans" <= str_0) );
+  VERIFY( "costa rica" <= str_0 );
+  VERIFY( str_0 <= "costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> "costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> "cost") );
+  VERIFY( std::is_lt(str_0 <=> "costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> "costa rica") );
+  VERIFY( std::is_lt("costa marbella" <=> str_0) );
+  VERIFY( std::is_lt("cost" <=> str_0) );
+  VERIFY( std::is_gt("costa ricans" <=> str_0) );
+  VERIFY( std::is_eq("costa rica" <=> str_0) );
+}
+
+int main()
+{
+  test01();
+}
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc 
b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc
new file mode 100644
index 00000000000..4dda0b5c0f5
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc
@@ -0,0 +1,194 @@
+// Copyright (C) 2020 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// C++20 21.3.3.2 Non-member comparison functions [string.cmp]
+
+// operator==
+/*
+template<class charT, class traits, class Allocator>
+  constexpr bool
+  operator==(const basic_string<charT, traits, Allocator>& lhs,
+            const basic_string<charT, traits, Allocator>& rhs);
+
+template<class charT, class traits, class Allocator>
+  constexpr bool
+  operator==(const basic_string<charT, traits, Allocator>& lhs,
+            const charT* rhs);
+*/
+
+// operator<=>
+/*
+template<class charT, class traits, class Allocator>
+  constexpr [see below]
+  operator<=>(const basic_string<charT, traits, Allocator>& lhs,
+             const basic_string<charT, traits, Allocator>& rhs);
+
+template<class charT, class traits, class Allocator>
+  constexpr [see below]
+  operator<=>(const basic_string<charT,traits,Allocator>& lhs,
+             const charT* rhs);
+*/
+
+#include <string>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::wstring         str_0(L"costa rica");
+  std::wstring         str_1(L"costa marbella");
+  std::wstring         str_2(L"cost");
+  std::wstring str_3(L"costa ricans");
+  std::wstring  str_4;
+
+  str_4 = str_0;
+  //comparisons between string objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string object and string literal
+  VERIFY( !(str_0 == L"costa marbella") );
+  VERIFY( !(str_0 == L"cost") );
+  VERIFY( !(str_0 == L"costa ricans") );
+  VERIFY( !(L"costa marbella" == str_0) );
+  VERIFY( !(L"cost" == str_0) );
+  VERIFY( !(L"costa ricans" == str_0) );
+  VERIFY( L"costa rica" == str_0 );
+  VERIFY( str_0 == L"costa rica" );
+
+  VERIFY( str_0 != L"costa marbella" );
+  VERIFY( str_0 != L"cost" );
+  VERIFY( str_0 != L"costa ricans" );
+  VERIFY( L"costa marbella" != str_0 );
+  VERIFY( L"cost" != str_0 );
+  VERIFY( L"costa ricans" != str_0 );
+  VERIFY( !(L"costa rica" != str_0) );
+  VERIFY( !(str_0 != L"costa rica") );
+
+  VERIFY( str_0 > L"costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > L"cost" );
+  VERIFY( !(str_0 > L"costa ricans") );
+  VERIFY( !(L"costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !(L"cost" > str_0) );
+  VERIFY( L"costa ricans" > str_0 );
+  VERIFY( !(L"costa rica" > str_0) );
+  VERIFY( !(str_0 > L"costa rica") );
+
+  VERIFY( !(str_0 < L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < L"cost") );
+  VERIFY( str_0 < L"costa ricans" );
+  VERIFY( L"costa marbella" < str_0 );//true cuz m<r
+  VERIFY( L"cost" < str_0 );
+  VERIFY( !(L"costa ricans" < str_0) );
+  VERIFY( !(L"costa rica" < str_0) );
+  VERIFY( !(str_0 < L"costa rica") );
+
+  VERIFY( str_0 >= L"costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= L"cost" );
+  VERIFY( !(str_0 >= L"costa ricans") );
+  VERIFY( !(L"costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !(L"cost" >= str_0) );
+  VERIFY( L"costa ricans" >= str_0 );
+  VERIFY( L"costa rica" >= str_0 );
+  VERIFY( str_0 >= L"costa rica" );
+
+  VERIFY( !(str_0 <= L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= L"cost") );
+  VERIFY( str_0 <= L"costa ricans" );
+  VERIFY( L"costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( L"cost" <= str_0 );
+  VERIFY( !(L"costa ricans" <= str_0) );
+  VERIFY( L"costa rica" <= str_0 );
+  VERIFY( str_0 <= L"costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> L"costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> L"cost") );
+  VERIFY( std::is_lt(str_0 <=> L"costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> L"costa rica") );
+  VERIFY( std::is_lt(L"costa marbella" <=> str_0) );
+  VERIFY( std::is_lt(L"cost" <=> str_0) );
+  VERIFY( std::is_gt(L"costa ricans" <=> str_0) );
+  VERIFY( std::is_eq(L"costa rica" <=> str_0) );
+}
+
+int main()
+{
+  test01();
+}
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
index f3042c25dc4..86a78108696 100644
--- 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
@@ -24,7 +24,7 @@ constexpr bool
 test01()
 {
   std::string_view s = "Everything changes and nothing stands still.";
-  char buf[7];
+  char buf[7]{};
   auto n = s.copy(buf, 7, 11);
   return std::string_view(buf, n) == "changes";
 }
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
index f48a17eade8..54df755c26b 100644
--- 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
@@ -24,7 +24,7 @@ constexpr bool
 test01()
 {
   std::wstring_view s = L"Everything changes and nothing stands still.";
-  wchar_t buf[7];
+  wchar_t buf[7]{};
   auto n = s.copy(buf, 7, 11);
   return std::wstring_view(buf, n) == L"changes";
 }
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/2.cc 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/2.cc
index 4a713c2c449..bd3921d2728 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/2.cc
@@ -1,4 +1,5 @@
 // { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
 
 // Copyright (C) 2013-2020 Free Software Foundation, Inc.
 //
@@ -17,97 +18,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// basic_string non-member functions
-
-// operator==
-/*
-template<class charT, class traits, class Allocator>
-  bool operator==(const basic_string<charT,traits,Allocator>& lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator==(const charT* lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator==(const basic_string<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-*/
-
-// operator!=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator!=(const basic_string<charT,traits,Allocator>& lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator!=(const charT* lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator!=(const basic_string<charT,traits,Allocator>& lhs, 
-                  const charT* rhs);
-*/
-
-// operator<
-/*
-template<class charT, class traits, class Allocator>
-  bool operator< (const basic_string<charT,traits,Allocator>& lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator< (const basic_string<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator< (const charT* lhs, 
-                  const basic_string<charT,traits,Allocator>& rhs);
-*/
-
-// operator>
-/*
-template<class charT, class traits, class Allocator>
-  bool operator> (const basic_string<charT,traits,Allocator>& lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator> (const basic_string<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator> (const charT* lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-*/
-
-// operator<=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator<=(const basic_string<charT,traits,Allocator>& lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator<=(const basic_string<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator<=(const charT* lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-*/
-
-// operator>=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator>=(const basic_string<charT,traits,Allocator>& lhs,
-                const basic_string<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator>=(const basic_string<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator>=(const charT* lhs,
-                  const basic_string<charT,traits,Allocator>& rhs);
-*/
+// C++17 24.4.3 Non-member comparison functions [string.view.comparison]
 
 #include <string_view>
 #include <testsuite_hooks.h>
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc
new file mode 100644
index 00000000000..e50b984c408
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc
@@ -0,0 +1,340 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2020 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// C++20 21.4.4 Non-member comparison functions [string.view.comparisons]
+
+// operator==
+/*
+template<class charT, class traits>
+  constexpr bool
+  operator==(basic_string_view<charT, traits> lhs,
+            basic_string_view<charT, traits> rhs) noexcept;
+
+template<class charT, class traits>
+  constexpr bool
+  operator==(basic_string_view<charT, traits> lhs,
+            type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
+*/
+
+// operator<=>
+/*
+template<class charT, class traits>
+  constexpr [see below]
+  operator<=>(basic_string_view<charT, traits> lhs,
+             basic_string_view<charT, traits> rhs) noexcept;
+
+template<class charT, class traits>
+  constexpr [see below]
+  operator<=>(basic_string_view<charT, traits> lhs,
+             type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
+*/
+
+#include <string_view>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::string_view     str_0("costa rica");
+  std::string_view     str_1("costa marbella");
+  std::string_view     str_2("cost");
+  std::string_view     str_3("costa ricans");
+  std::string_view        str_4;
+
+  str_4 = str_0;
+  //comparisons between string objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string object and string literal
+  VERIFY( !(str_0 == "costa marbella") );
+  VERIFY( !(str_0 == "cost") );
+  VERIFY( !(str_0 == "costa ricans") );
+  VERIFY( !("costa marbella" == str_0) );
+  VERIFY( !("cost" == str_0) );
+  VERIFY( !("costa ricans" == str_0) );
+  VERIFY( "costa rica" == str_0 );
+  VERIFY( str_0 == "costa rica" );
+
+  VERIFY( str_0 != "costa marbella" );
+  VERIFY( str_0 != "cost" );
+  VERIFY( str_0 != "costa ricans" );
+  VERIFY( "costa marbella" != str_0 );
+  VERIFY( "cost" != str_0 );
+  VERIFY( "costa ricans" != str_0 );
+  VERIFY( !("costa rica" != str_0) );
+  VERIFY( !(str_0 != "costa rica") );
+
+  VERIFY( str_0 > "costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > "cost" );
+  VERIFY( !(str_0 > "costa ricans") );
+  VERIFY( !("costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !("cost" > str_0) );
+  VERIFY( "costa ricans" > str_0 );
+  VERIFY( !("costa rica" > str_0) );
+  VERIFY( !(str_0 > "costa rica") );
+
+  VERIFY( !(str_0 < "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < "cost") );
+  VERIFY( str_0 < "costa ricans" );
+  VERIFY( "costa marbella" < str_0 );//true cuz m<r
+  VERIFY( "cost" < str_0 );
+  VERIFY( !("costa ricans" < str_0) );
+  VERIFY( !("costa rica" < str_0) );
+  VERIFY( !(str_0 < "costa rica") );
+
+  VERIFY( str_0 >= "costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= "cost" );
+  VERIFY( !(str_0 >= "costa ricans") );
+  VERIFY( !("costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !("cost" >= str_0) );
+  VERIFY( "costa ricans" >= str_0 );
+  VERIFY( "costa rica" >= str_0 );
+  VERIFY( str_0 >= "costa rica" );
+
+  VERIFY( !(str_0 <= "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= "cost") );
+  VERIFY( str_0 <= "costa ricans" );
+  VERIFY( "costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( "cost" <= str_0 );
+  VERIFY( !("costa ricans" <= str_0) );
+  VERIFY( "costa rica" <= str_0 );
+  VERIFY( str_0 <= "costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> "costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> "cost") );
+  VERIFY( std::is_lt(str_0 <=> "costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> "costa rica") );
+  VERIFY( std::is_lt("costa marbella" <=> str_0) );
+  VERIFY( std::is_lt("cost" <=> str_0) );
+  VERIFY( std::is_gt("costa ricans" <=> str_0) );
+  VERIFY( std::is_eq("costa rica" <=> str_0) );
+}
+
+constexpr bool
+test02()
+{
+  std::string_view     str_0("costa rica");
+  std::string_view     str_1("costa marbella");
+  std::string_view     str_2("cost");
+  std::string_view     str_3("costa ricans");
+  std::string_view        str_4;
+
+#undef VERIFY
+#define VERIFY(x) if (!(x)) return false
+
+  str_4 = str_0;
+  //comparisons between string objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string object and string literal
+  VERIFY( !(str_0 == "costa marbella") );
+  VERIFY( !(str_0 == "cost") );
+  VERIFY( !(str_0 == "costa ricans") );
+  VERIFY( !("costa marbella" == str_0) );
+  VERIFY( !("cost" == str_0) );
+  VERIFY( !("costa ricans" == str_0) );
+  VERIFY( "costa rica" == str_0 );
+  VERIFY( str_0 == "costa rica" );
+
+  VERIFY( str_0 != "costa marbella" );
+  VERIFY( str_0 != "cost" );
+  VERIFY( str_0 != "costa ricans" );
+  VERIFY( "costa marbella" != str_0 );
+  VERIFY( "cost" != str_0 );
+  VERIFY( "costa ricans" != str_0 );
+  VERIFY( !("costa rica" != str_0) );
+  VERIFY( !(str_0 != "costa rica") );
+
+  VERIFY( str_0 > "costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > "cost" );
+  VERIFY( !(str_0 > "costa ricans") );
+  VERIFY( !("costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !("cost" > str_0) );
+  VERIFY( "costa ricans" > str_0 );
+  VERIFY( !("costa rica" > str_0) );
+  VERIFY( !(str_0 > "costa rica") );
+
+  VERIFY( !(str_0 < "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < "cost") );
+  VERIFY( str_0 < "costa ricans" );
+  VERIFY( "costa marbella" < str_0 );//true cuz m<r
+  VERIFY( "cost" < str_0 );
+  VERIFY( !("costa ricans" < str_0) );
+  VERIFY( !("costa rica" < str_0) );
+  VERIFY( !(str_0 < "costa rica") );
+
+  VERIFY( str_0 >= "costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= "cost" );
+  VERIFY( !(str_0 >= "costa ricans") );
+  VERIFY( !("costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !("cost" >= str_0) );
+  VERIFY( "costa ricans" >= str_0 );
+  VERIFY( "costa rica" >= str_0 );
+  VERIFY( str_0 >= "costa rica" );
+
+  VERIFY( !(str_0 <= "costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= "cost") );
+  VERIFY( str_0 <= "costa ricans" );
+  VERIFY( "costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( "cost" <= str_0 );
+  VERIFY( !("costa ricans" <= str_0) );
+  VERIFY( "costa rica" <= str_0 );
+  VERIFY( str_0 <= "costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> "costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> "cost") );
+  VERIFY( std::is_lt(str_0 <=> "costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> "costa rica") );
+  VERIFY( std::is_lt("costa marbella" <=> str_0) );
+  VERIFY( std::is_lt("cost" <=> str_0) );
+  VERIFY( std::is_gt("costa ricans" <=> str_0) );
+  VERIFY( std::is_eq("costa rica" <=> str_0) );
+
+  return true;
+}
+
+int
+main()
+{
+  test01();
+  static_assert( test02() );
+}
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc
index c070d67732b..c6d5de3dce0 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc
@@ -1,4 +1,5 @@
 // { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
 
 // Copyright (C) 2013-2020 Free Software Foundation, Inc.
 //
@@ -17,97 +18,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// basic_string_view non-member functions
-
-// operator==
-/*
-template<class charT, class traits, class Allocator>
-  bool operator==(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator==(const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator==(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-*/
-
-// operator!=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator!=(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator!=(const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator!=(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-*/
-
-// operator<
-/*
-template<class charT, class traits, class Allocator>
-  bool operator< (const basic_string_view<charT,traits,Allocator>& lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator< (const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator< (const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-*/
-
-// operator>
-/*
-template<class charT, class traits, class Allocator>
-  bool operator> (const basic_string_view<charT,traits,Allocator>& lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator> (const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator> (const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-*/
-
-// operator<=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator<=(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator<=(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator<=(const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-*/
-
-// operator>=
-/*
-template<class charT, class traits, class Allocator>
-  bool operator>=(const basic_string_view<charT,traits,Allocator>& lhs,
-                const basic_string_view<charT,traits,Allocator>& rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator>=(const basic_string_view<charT,traits,Allocator>& lhs,
-                  const charT* rhs);
-
-template<class charT, class traits, class Allocator>
-  bool operator>=(const charT* lhs,
-                  const basic_string_view<charT,traits,Allocator>& rhs);
-*/
+// C++17 24.4.3 Non-member comparison functions [string.view.comparison]
 
 #include <string_view>
 #include <testsuite_hooks.h>
diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc
new file mode 100644
index 00000000000..bb8e3496ba2
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc
@@ -0,0 +1,340 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2020 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// C++20 21.4.4 Non-member comparison functions [string.view.comparisons]
+
+// operator==
+/*
+template<class charT, class traits>
+  constexpr bool
+  operator==(basic_string_view<charT, traits> lhs,
+            basic_string_view<charT, traits> rhs) noexcept;
+
+template<class charT, class traits>
+  constexpr bool
+  operator==(basic_string_view<charT, traits> lhs,
+            type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
+*/
+
+// operator<=>
+/*
+template<class charT, class traits>
+  constexpr [see below]
+  operator<=>(basic_string_view<charT, traits> lhs,
+             basic_string_view<charT, traits> rhs) noexcept;
+
+template<class charT, class traits>
+  constexpr [see below]
+  operator<=>(basic_string_view<charT, traits> lhs,
+             type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
+*/
+
+#include <string_view>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::wstring_view    str_0(L"costa rica");
+  std::wstring_view    str_1(L"costa marbella");
+  std::wstring_view    str_2(L"cost");
+  std::wstring_view    str_3(L"costa ricans");
+  std::wstring_view  str_4;
+
+  str_4 = str_0;
+  //comparisons between string_view objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string_view object and string_view literal
+  VERIFY( !(str_0 == L"costa marbella") );
+  VERIFY( !(str_0 == L"cost") );
+  VERIFY( !(str_0 == L"costa ricans") );
+  VERIFY( !(L"costa marbella" == str_0) );
+  VERIFY( !(L"cost" == str_0) );
+  VERIFY( !(L"costa ricans" == str_0) );
+  VERIFY( L"costa rica" == str_0 );
+  VERIFY( str_0 == L"costa rica" );
+
+  VERIFY( str_0 != L"costa marbella" );
+  VERIFY( str_0 != L"cost" );
+  VERIFY( str_0 != L"costa ricans" );
+  VERIFY( L"costa marbella" != str_0 );
+  VERIFY( L"cost" != str_0 );
+  VERIFY( L"costa ricans" != str_0 );
+  VERIFY( !(L"costa rica" != str_0) );
+  VERIFY( !(str_0 != L"costa rica") );
+
+  VERIFY( str_0 > L"costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > L"cost" );
+  VERIFY( !(str_0 > L"costa ricans") );
+  VERIFY( !(L"costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !(L"cost" > str_0) );
+  VERIFY( L"costa ricans" > str_0 );
+  VERIFY( !(L"costa rica" > str_0) );
+  VERIFY( !(str_0 > L"costa rica") );
+
+  VERIFY( !(str_0 < L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < L"cost") );
+  VERIFY( str_0 < L"costa ricans" );
+  VERIFY( L"costa marbella" < str_0 );//true cuz m<r
+  VERIFY( L"cost" < str_0 );
+  VERIFY( !(L"costa ricans" < str_0) );
+  VERIFY( !(L"costa rica" < str_0) );
+  VERIFY( !(str_0 < L"costa rica") );
+
+  VERIFY( str_0 >= L"costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= L"cost" );
+  VERIFY( !(str_0 >= L"costa ricans") );
+  VERIFY( !(L"costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !(L"cost" >= str_0) );
+  VERIFY( L"costa ricans" >= str_0 );
+  VERIFY( L"costa rica" >= str_0 );
+  VERIFY( str_0 >= L"costa rica" );
+
+  VERIFY( !(str_0 <= L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= L"cost") );
+  VERIFY( str_0 <= L"costa ricans" );
+  VERIFY( L"costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( L"cost" <= str_0 );
+  VERIFY( !(L"costa ricans" <= str_0) );
+  VERIFY( L"costa rica" <= str_0 );
+  VERIFY( str_0 <= L"costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> L"costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> L"cost") );
+  VERIFY( std::is_lt(str_0 <=> L"costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> L"costa rica") );
+  VERIFY( std::is_lt(L"costa marbella" <=> str_0) );
+  VERIFY( std::is_lt(L"cost" <=> str_0) );
+  VERIFY( std::is_gt(L"costa ricans" <=> str_0) );
+  VERIFY( std::is_eq(L"costa rica" <=> str_0) );
+}
+
+constexpr bool
+test02()
+{
+  std::wstring_view    str_0(L"costa rica");
+  std::wstring_view    str_1(L"costa marbella");
+  std::wstring_view    str_2(L"cost");
+  std::wstring_view    str_3(L"costa ricans");
+  std::wstring_view  str_4;
+
+#undef VERIFY
+#define VERIFY(x) if (!(x)) return false
+
+  str_4 = str_0;
+  //comparisons between string_view objects
+  VERIFY( !(str_0 == str_1) );
+  VERIFY( !(str_0 == str_2) );
+  VERIFY( !(str_0 == str_3) );
+  VERIFY( !(str_1 == str_0) );
+  VERIFY( !(str_2 == str_0) );
+  VERIFY( !(str_3 == str_0) );
+  VERIFY( str_4 == str_0 );
+  VERIFY( str_0 == str_4 );
+
+  VERIFY( str_0 != str_1 );
+  VERIFY( str_0 != str_2 );
+  VERIFY( str_0 != str_3 );
+  VERIFY( str_1 != str_0 );
+  VERIFY( str_2 != str_0 );
+  VERIFY( str_3 != str_0 );
+  VERIFY( !(str_0 != str_4) );
+  VERIFY( !(str_4 != str_0) );
+
+  VERIFY( str_0 > str_1 ); //true cuz r>m
+  VERIFY( str_0 > str_2 );
+  VERIFY( !(str_0 > str_3) );
+  VERIFY( !(str_1 > str_0) ); //false cuz m<r
+  VERIFY( !(str_2 > str_0) );
+  VERIFY( str_3 > str_0 );
+  VERIFY( !(str_0 > str_4) );
+  VERIFY( !(str_4 > str_0) );
+
+  VERIFY( !(str_0 < str_1) ); //false cuz r>m
+  VERIFY( !(str_0 < str_2) );
+  VERIFY( str_0 < str_3 );
+  VERIFY( str_1 < str_0 ); //true cuz m<r
+  VERIFY( str_2 < str_0 );
+  VERIFY( !(str_3 < str_0) );
+  VERIFY( !(str_0 < str_4) );
+  VERIFY( !(str_4 < str_0) );
+
+  VERIFY( str_0 >= str_1 ); //true cuz r>m
+  VERIFY( str_0 >= str_2 );
+  VERIFY( !(str_0 >= str_3) );
+  VERIFY( !(str_1 >= str_0) );//false cuz m<r
+  VERIFY( !(str_2 >= str_0) );
+  VERIFY( str_3 >= str_0 );
+  VERIFY( str_0 >= str_4 );
+  VERIFY( str_4 >= str_0 );
+
+  VERIFY( !(str_0 <= str_1) );//false cuz r>m
+  VERIFY( !(str_0 <= str_2) );
+  VERIFY( str_0 <= str_3 );
+  VERIFY( str_1 <= str_0 );//true cuz m<r
+  VERIFY( str_2 <= str_0 );
+  VERIFY( !(str_3 <= str_0) );
+  VERIFY( str_0 <= str_4 );
+  VERIFY( str_4 <= str_0 );
+
+  VERIFY( std::is_gt(str_0 <=> str_1) );
+  VERIFY( std::is_gt(str_0 <=> str_2) );
+  VERIFY( std::is_lt(str_0 <=> str_3) );
+  VERIFY( std::is_eq(str_0 <=> str_4) );
+  VERIFY( std::is_lt(str_1 <=> str_0) );
+  VERIFY( std::is_lt(str_2 <=> str_0) );
+  VERIFY( std::is_gt(str_3 <=> str_0) );
+  VERIFY( std::is_eq(str_4 <=> str_0) );
+
+  //comparisons between string_view object and string_view literal
+  VERIFY( !(str_0 == L"costa marbella") );
+  VERIFY( !(str_0 == L"cost") );
+  VERIFY( !(str_0 == L"costa ricans") );
+  VERIFY( !(L"costa marbella" == str_0) );
+  VERIFY( !(L"cost" == str_0) );
+  VERIFY( !(L"costa ricans" == str_0) );
+  VERIFY( L"costa rica" == str_0 );
+  VERIFY( str_0 == L"costa rica" );
+
+  VERIFY( str_0 != L"costa marbella" );
+  VERIFY( str_0 != L"cost" );
+  VERIFY( str_0 != L"costa ricans" );
+  VERIFY( L"costa marbella" != str_0 );
+  VERIFY( L"cost" != str_0 );
+  VERIFY( L"costa ricans" != str_0 );
+  VERIFY( !(L"costa rica" != str_0) );
+  VERIFY( !(str_0 != L"costa rica") );
+
+  VERIFY( str_0 > L"costa marbella" ); //true cuz r>m
+  VERIFY( str_0 > L"cost" );
+  VERIFY( !(str_0 > L"costa ricans") );
+  VERIFY( !(L"costa marbella" > str_0) );//false cuz m<r
+  VERIFY( !(L"cost" > str_0) );
+  VERIFY( L"costa ricans" > str_0 );
+  VERIFY( !(L"costa rica" > str_0) );
+  VERIFY( !(str_0 > L"costa rica") );
+
+  VERIFY( !(str_0 < L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 < L"cost") );
+  VERIFY( str_0 < L"costa ricans" );
+  VERIFY( L"costa marbella" < str_0 );//true cuz m<r
+  VERIFY( L"cost" < str_0 );
+  VERIFY( !(L"costa ricans" < str_0) );
+  VERIFY( !(L"costa rica" < str_0) );
+  VERIFY( !(str_0 < L"costa rica") );
+
+  VERIFY( str_0 >= L"costa marbella" );//true cuz r>m
+  VERIFY( str_0 >= L"cost" );
+  VERIFY( !(str_0 >= L"costa ricans") );
+  VERIFY( !(L"costa marbella" >= str_0) );//false cuz m<r
+  VERIFY( !(L"cost" >= str_0) );
+  VERIFY( L"costa ricans" >= str_0 );
+  VERIFY( L"costa rica" >= str_0 );
+  VERIFY( str_0 >= L"costa rica" );
+
+  VERIFY( !(str_0 <= L"costa marbella") );//false cuz r>m
+  VERIFY( !(str_0 <= L"cost") );
+  VERIFY( str_0 <= L"costa ricans" );
+  VERIFY( L"costa marbella" <= str_0 );//true cuz m<r
+  VERIFY( L"cost" <= str_0 );
+  VERIFY( !(L"costa ricans" <= str_0) );
+  VERIFY( L"costa rica" <= str_0 );
+  VERIFY( str_0 <= L"costa rica" );
+
+  VERIFY( std::is_gt(str_0 <=> L"costa marbella") );
+  VERIFY( std::is_gt(str_0 <=> L"cost") );
+  VERIFY( std::is_lt(str_0 <=> L"costa ricans") );
+  VERIFY( std::is_eq(str_0 <=> L"costa rica") );
+  VERIFY( std::is_lt(L"costa marbella" <=> str_0) );
+  VERIFY( std::is_lt(L"cost" <=> str_0) );
+  VERIFY( std::is_gt(L"costa ricans" <=> str_0) );
+  VERIFY( std::is_eq(L"costa rica" <=> str_0) );
+
+  return true;
+}
+
+int
+main()
+{
+  test01();
+  static_assert( test02() );
+}
diff --git a/libstdc++-v3/testsuite/28_regex/sub_match/compare_c++20.cc 
b/libstdc++-v3/testsuite/28_regex/sub_match/compare_c++20.cc
new file mode 100644
index 00000000000..d632d002f20
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/sub_match/compare_c++20.cc
@@ -0,0 +1,335 @@
+// Copyright (C) 2018-2020 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+template<typename C> struct traits : std::char_traits<C> { };
+
+void
+test01()
+{
+  const std::basic_string<char, traits<char>> s0, s1 = "1";
+  const std::ssub_match sm, sm2;
+
+  VERIFY( sm.compare(sm) == 0 );
+  VERIFY( sm.compare(sm2) == 0 );
+  VERIFY( sm.compare(sm.str()) == 0 );
+  VERIFY( sm.compare(sm.str().c_str()) == 0 );
+  VERIFY( sm.compare(sm2.str()) == 0 );
+  VERIFY( sm.compare(sm2.str().c_str()) == 0 );
+  VERIFY( sm.compare(std::string(s1.c_str())) == -1 );
+  VERIFY( sm.compare(s1.c_str()) == -1 );
+
+
+  VERIFY( sm == sm2 );
+  VERIFY( !(sm != sm2) );
+  VERIFY( !(sm < sm2) );
+  VERIFY( !(sm > sm2) );
+  VERIFY( sm <= sm2 );
+  VERIFY( sm >= sm2 );
+  VERIFY( std::is_eq(sm <=> sm2) );
+
+  VERIFY( sm == s0 );
+  VERIFY( !(sm != s0) );
+  VERIFY( !(sm < s0) );
+  VERIFY( !(sm > s0) );
+  VERIFY( sm <= s0 );
+  VERIFY( sm >= s0 );
+  VERIFY( std::is_eq(sm <=> s0) );
+
+  VERIFY( s0 == sm );
+  VERIFY( !(s0 != sm) );
+  VERIFY( !(s0 < sm) );
+  VERIFY( !(s0 > sm) );
+  VERIFY( s0 <= sm );
+  VERIFY( s0 >= sm );
+  VERIFY( std::is_eq(s0 <=> sm) );
+
+  VERIFY( sm == s0.c_str() );
+  VERIFY( !(sm != s0.c_str()) );
+  VERIFY( !(sm < s0.c_str()) );
+  VERIFY( !(sm > s0.c_str()) );
+  VERIFY( sm <= s0.c_str() );
+  VERIFY( sm >= s0.c_str() );
+  VERIFY( std::is_eq(sm <=> s0.c_str()) );
+
+  VERIFY( s0.c_str() == sm );
+  VERIFY( !(s0.c_str() != sm) );
+  VERIFY( !(s0.c_str() < sm) );
+  VERIFY( !(s0.c_str() > sm) );
+  VERIFY( s0.c_str() <= sm );
+  VERIFY( s0.c_str() >= sm );
+  VERIFY( std::is_eq(s0.c_str() <=> sm) );
+
+  VERIFY( !(sm == s1) );
+  VERIFY( sm != s1 );
+  VERIFY( sm < s1 );
+  VERIFY( !(sm > s1) );
+  VERIFY( sm <= s1 );
+  VERIFY( !(sm >= s1) );
+  VERIFY( std::is_lt(sm <=> s1) );
+
+  VERIFY( !(sm == s1.c_str()) );
+  VERIFY( sm != s1.c_str() );
+  VERIFY( sm < s1.c_str() );
+  VERIFY( !(sm > s1.c_str()) );
+  VERIFY( sm <= s1.c_str() );
+  VERIFY( !(sm >= s1.c_str()) );
+  VERIFY( std::is_lt(sm <=> s1.c_str()) );
+
+  VERIFY( !(s1.c_str() == sm) );
+  VERIFY( s1.c_str() != sm );
+  VERIFY( !(s1.c_str() < sm) );
+  VERIFY( s1.c_str() > sm );
+  VERIFY( !(s1.c_str() <= sm) );
+  VERIFY( s1.c_str() >= sm );
+  VERIFY( std::is_gt(s1.c_str() <=> sm) );
+
+  VERIFY( !(sm == s1[0]) );
+  VERIFY( sm != s1[0] );
+  VERIFY( sm < s1[0] );
+  VERIFY( !(sm > s1[0]) );
+  VERIFY( sm <= s1[0] );
+  VERIFY( !(sm >= s1[0]) );
+  VERIFY( std::is_lt(sm <=> s1[0]) );
+
+  VERIFY( !(s1[0] == sm) );
+  VERIFY( s1[0] != sm );
+  VERIFY( !(s1[0] < sm) );
+  VERIFY( s1[0] > sm );
+  VERIFY( !(s1[0] <= sm) );
+  VERIFY( s1[0] >= sm );
+  VERIFY( std::is_gt(s1[0] <=> sm) );
+}
+
+void
+test02()
+{
+  const std::basic_string<char, traits<char>> s0, s1 = "1";
+  std::csub_match sm;
+  const std::csub_match sm2;
+  const char c[] = "1";
+  sm.matched = true;
+  sm.first = c;
+  sm.second = c+1;
+
+  VERIFY( sm.compare(sm) == 0 );
+  VERIFY( sm.compare(sm2) == 1 );
+  VERIFY( sm.compare(sm.str()) == 0 );
+  VERIFY( sm.compare(sm.str().c_str()) == 0 );
+  VERIFY( sm.compare(sm2.str()) == 1 );
+  VERIFY( sm.compare(sm2.str().c_str()) == 1 );
+  VERIFY( sm.compare(std::string(s1.c_str())) == 0 );
+  VERIFY( sm.compare(s1.c_str()) == 0 );
+
+  VERIFY( !(sm == sm2) );
+  VERIFY( sm != sm2 );
+  VERIFY( !(sm < sm2) );
+  VERIFY( sm > sm2 );
+  VERIFY( !(sm <= sm2) );
+  VERIFY( sm >= sm2 );
+  VERIFY( std::is_gt(sm <=> sm2) );
+
+  VERIFY( !(sm2 == sm) );
+  VERIFY( sm2 != sm );
+  VERIFY( sm2 < sm );
+  VERIFY( !(sm2 > sm) );
+  VERIFY( sm2 <= sm );
+  VERIFY( !(sm2 >= sm) );
+  VERIFY( std::is_lt(sm2 <=> sm) );
+
+  VERIFY( !(sm == s0) );
+  VERIFY( sm != s0 );
+  VERIFY( !(sm < s0) );
+  VERIFY( sm > s0 );
+  VERIFY( !(sm <= s0) );
+  VERIFY( sm >= s0 );
+  VERIFY( std::is_gt(sm <=> s0) );
+
+  VERIFY( !(sm == s0.c_str()) );
+  VERIFY( sm != s0.c_str() );
+  VERIFY( !(sm < s0.c_str()) );
+  VERIFY( sm > s0.c_str() );
+  VERIFY( !(sm <= s0.c_str()) );
+  VERIFY( sm >= s0.c_str() );
+  VERIFY( std::is_gt(sm <=> s0.c_str()) );
+
+  VERIFY( !(s0.c_str() == sm) );
+  VERIFY( s0.c_str() != sm );
+  VERIFY( s0.c_str() < sm );
+  VERIFY( !(s0.c_str() > sm) );
+  VERIFY( s0.c_str() <= sm );
+  VERIFY( !(s0.c_str() >= sm) );
+  VERIFY( std::is_lt(s0.c_str() <=> sm) );
+
+  VERIFY( s1 == sm );
+  VERIFY( !(s1 != sm) );
+  VERIFY( !(s1 < sm) );
+  VERIFY( !(s1 > sm) );
+  VERIFY( s1 <= sm );
+  VERIFY( s1 >= sm );
+  VERIFY( std::is_eq(s1 <=> sm) );
+
+  VERIFY( sm == s1.c_str() );
+  VERIFY( !(sm != s1.c_str()) );
+  VERIFY( !(sm < s1.c_str()) );
+  VERIFY( !(sm > s1.c_str()) );
+  VERIFY( sm <= s1.c_str() );
+  VERIFY( sm >= s1.c_str() );
+  VERIFY( std::is_eq(sm <=> s1.c_str()) );
+
+  VERIFY( s1.c_str() == sm );
+  VERIFY( !(s1.c_str() != sm) );
+  VERIFY( !(s1.c_str() < sm) );
+  VERIFY( !(s1.c_str() > sm) );
+  VERIFY( s1.c_str() <= sm );
+  VERIFY( s1.c_str() >= sm );
+  VERIFY( std::is_eq(s1.c_str() <=> sm) );
+
+  VERIFY( sm == s1[0] );
+  VERIFY( !(sm != s1[0]) );
+  VERIFY( !(sm < s1[0]) );
+  VERIFY( !(sm > s1[0]) );
+  VERIFY( sm <= s1[0] );
+  VERIFY( sm >= s1[0] );
+  VERIFY( std::is_eq(sm <=> s1[0]) );
+
+  VERIFY( s1[0] == sm );
+  VERIFY( !(s1[0] != sm) );
+  VERIFY( !(s1[0] < sm) );
+  VERIFY( !(s1[0] > sm) );
+  VERIFY( s1[0] <= sm );
+  VERIFY( s1[0] >= sm );
+  VERIFY( std::is_eq(s1[0] <=> sm) );
+}
+
+void
+test03()
+{
+  const std::basic_string<char, traits<char>> s0, s1 = "1";
+  const char c[] = "1";
+  test_container<const char, bidirectional_iterator_wrapper> tc(c, c+1);
+  std::sub_match<bidirectional_iterator_wrapper<const char>> sm;
+  const std::sub_match<bidirectional_iterator_wrapper<const char>> sm2;
+  sm.matched = true;
+  sm.first = tc.begin();
+  sm.second = tc.end();
+
+  VERIFY( sm.compare(sm) == 0 );
+  VERIFY( sm.compare(sm2) == 1 );
+  VERIFY( sm.compare(sm.str()) == 0 );
+  VERIFY( sm.compare(sm.str().c_str()) == 0 );
+  VERIFY( sm.compare(sm2.str()) == 1 );
+  VERIFY( sm.compare(sm2.str().c_str()) == 1 );
+  VERIFY( sm.compare(std::string(s1.c_str())) == 0 );
+  VERIFY( sm.compare(s1.c_str()) == 0 );
+
+  VERIFY( !(sm == sm2) );
+  VERIFY( sm != sm2 );
+  VERIFY( !(sm < sm2) );
+  VERIFY( sm > sm2 );
+  VERIFY( !(sm <= sm2) );
+  VERIFY( sm >= sm2 );
+  VERIFY( std::is_gt(sm <=> sm2) );
+
+  VERIFY( !(sm2 == sm) );
+  VERIFY( sm2 != sm );
+  VERIFY( sm2 < sm );
+  VERIFY( !(sm2 > sm) );
+  VERIFY( sm2 <= sm );
+  VERIFY( !(sm2 >= sm) );
+  VERIFY( std::is_lt(sm2 <=> sm) );
+
+  VERIFY( !(sm == s0) );
+  VERIFY( sm != s0 );
+  VERIFY( !(sm < s0) );
+  VERIFY( sm > s0 );
+  VERIFY( !(sm <= s0) );
+  VERIFY( sm >= s0 );
+  VERIFY( std::is_gt(sm <=> s0) );
+
+  VERIFY( !(sm == s0.c_str()) );
+  VERIFY( sm != s0.c_str() );
+  VERIFY( !(sm < s0.c_str()) );
+  VERIFY( sm > s0.c_str() );
+  VERIFY( !(sm <= s0.c_str()) );
+  VERIFY( sm >= s0.c_str() );
+  VERIFY( std::is_gt(sm <=> s0.c_str()) );
+
+  VERIFY( !(s0.c_str() == sm) );
+  VERIFY( s0.c_str() != sm );
+  VERIFY( s0.c_str() < sm );
+  VERIFY( !(s0.c_str() > sm) );
+  VERIFY( s0.c_str() <= sm );
+  VERIFY( !(s0.c_str() >= sm) );
+  VERIFY( std::is_lt(s0.c_str() <=> sm) );
+
+  VERIFY( s1 == sm );
+  VERIFY( !(s1 != sm) );
+  VERIFY( !(s1 < sm) );
+  VERIFY( !(s1 > sm) );
+  VERIFY( s1 <= sm );
+  VERIFY( s1 >= sm );
+  VERIFY( std::is_eq(s1 <=> sm) );
+
+  VERIFY( sm == s1.c_str() );
+  VERIFY( !(sm != s1.c_str()) );
+  VERIFY( !(sm < s1.c_str()) );
+  VERIFY( !(sm > s1.c_str()) );
+  VERIFY( sm <= s1.c_str() );
+  VERIFY( sm >= s1.c_str() );
+  VERIFY( std::is_eq(sm <=> s1.c_str()) );
+
+  VERIFY( s1.c_str() == sm );
+  VERIFY( !(s1.c_str() != sm) );
+  VERIFY( !(s1.c_str() < sm) );
+  VERIFY( !(s1.c_str() > sm) );
+  VERIFY( s1.c_str() <= sm );
+  VERIFY( s1.c_str() >= sm );
+  VERIFY( std::is_eq(s1.c_str() <=> sm) );
+
+  VERIFY( sm == s1[0] );
+  VERIFY( !(sm != s1[0]) );
+  VERIFY( !(sm < s1[0]) );
+  VERIFY( !(sm > s1[0]) );
+  VERIFY( sm <= s1[0] );
+  VERIFY( sm >= s1[0] );
+  VERIFY( std::is_eq(sm <=> s1[0]) );
+
+  VERIFY( s1[0] == sm );
+  VERIFY( !(s1[0] != sm) );
+  VERIFY( !(s1[0] < sm) );
+  VERIFY( !(s1[0] > sm) );
+  VERIFY( s1[0] <= sm );
+  VERIFY( s1[0] >= sm );
+  VERIFY( std::is_eq(s1[0] <=> sm) );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+}

Reply via email to