libstdc++: Add comparison operators for string and regex types
authorJonathan Wakely <jwakely@redhat.com>
Fri, 17 Apr 2020 15:24:49 +0000 (16:24 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 17 Apr 2020 15:40:11 +0000 (16:40 +0100)
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.

14 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/bits/char_traits.h
libstdc++-v3/include/bits/regex.h
libstdc++-v3/include/std/string_view
libstdc++-v3/testsuite/21_strings/basic_string/operators/char/cmp_c++20.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/cmp_c++20.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/2.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/cmp_c++20.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/2.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/cmp_c++20.cc [new file with mode: 0644]
libstdc++-v3/testsuite/28_regex/sub_match/compare_c++20.cc [new file with mode: 0644]

index cd3bbca35baeafaad3e655ada8ebdd18dfe9f0b2..d24c757d00ab95cea434dce1ef5050df03ba07ad 100644 (file)
@@ -1,3 +1,36 @@
+2020-04-17  Jonathan Wakely  <jwakely@redhat.com>
+
+       * 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.
+
 2020-04-16  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/20_util/unsynchronized_pool_resource/allocate.cc: Remove
index 0374f8e68051b29526533bb9c3245ff365c405ce..bc0c256b65e4893ed6dba1f29557ec5310e49aeb 100644 (file)
@@ -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.
index 65031d3ac8330381f146aa798e8a78a9e166e0f7..c6da184e4bd4292546ad45626f58ae0313f69c28 100644 (file)
@@ -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
 
index dcae83eea4e5bdee72a8bfce63a3ff048606ed7d..6db05889e8cecaa84c22921b0f79978eaa62154f 100644 (file)
@@ -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
   /**
index ea1ccc9bb2192cd4589a05de5fa69c3bbfa85044..b5d8eab2f337d98a5e0c42e474a61d8d756c179e 100644 (file)
@@ -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 (file)
index 0000000..b62d10b
--- /dev/null
@@ -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 (file)
index 0000000..4dda0b5
--- /dev/null
@@ -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();
+}
index f3042c25dc43584a7b36954491eaa424b3229d9c..86a78108696b759aca2f5ea0621c3ef2fd6c072d 100644 (file)
@@ -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";
 }
index f48a17eade8f268c0d72af4b8b9943c5173dc809..54df755c26bee68df2fc3582d12b5846d63f0bf8 100644 (file)
@@ -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";
 }
index 4a713c2c44949056752f625b94283566db9bf974..bd3921d27284e16c9e656461d45d7df5b5f6b7f2 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
 
 // Copyright (C) 2013-2020 Free Software Foundation, Inc.
 //
 // 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 (file)
index 0000000..e50b984
--- /dev/null
@@ -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() );
+}
index c070d67732bc6b40116dbe5eefa1d3c9aafa9f53..c6d5de3dce02a8ec08be56ae5bc20dc772de28cd 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
 
 // Copyright (C) 2013-2020 Free Software Foundation, Inc.
 //
 // 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 (file)
index 0000000..bb8e349
--- /dev/null
@@ -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 (file)
index 0000000..d632d00
--- /dev/null
@@ -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();
+}