summaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
authorHristo Hristov <zingam@outlook.com>2023-05-06 15:41:41 +0300
committerHristo Hristov <zingam@outlook.com>2023-05-08 17:03:06 +0300
commit254986d2df8d8407b46329e452c16748d29ed4cd (patch)
treef7e8afaf2d277af6046189b0b566865431842279 /libcxx
parente875de2a3e8e814265c7cb09b908a444df1a498d (diff)
downloadllvm-254986d2df8d8407b46329e452c16748d29ed4cd.tar.gz
[libc++][spaceship] Implement `operator<=>` for `array`
Implements part of P1614R2 "The Mothership has Landed" Reviewed By: Mordante, #libc, philnik Differential Revision: https://reviews.llvm.org/D132265
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/docs/Status/Cxx20Issues.csv2
-rw-r--r--libcxx/docs/Status/SpaceshipProjects.csv3
-rw-r--r--libcxx/include/array55
-rw-r--r--libcxx/test/std/containers/sequences/array/compare.fail.cpp68
-rw-r--r--libcxx/test/std/containers/sequences/array/compare.pass.cpp103
-rw-r--r--libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp87
-rw-r--r--libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp37
-rw-r--r--libcxx/test/std/containers/sequences/array/compare.verify.cpp58
-rw-r--r--libcxx/test/support/test_container_comparisons.h8
9 files changed, 273 insertions, 148 deletions
diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index c0143931be01..d9f87112a5e6 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -259,7 +259,7 @@
"`3338 <https://wg21.link/LWG3338>`__","Rename ``default_constructible``\ to ``default_initializable``\ ","Prague","|Complete|","13.0"
"`3340 <https://wg21.link/LWG3340>`__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","Prague","|Complete|","14.0","|format|"
"`3346 <https://wg21.link/LWG3346>`__","``pair``\ and ``tuple``\ copy and move constructor have backwards specification","Prague","",""
-"`3347 <https://wg21.link/LWG3347>`__","``std::pair<T, U>``\ now requires ``T``\ and ``U``\ to be less-than-comparable","Prague","",""
+"`3347 <https://wg21.link/LWG3347>`__","``std::pair<T, U>``\ now requires ``T``\ and ``U``\ to be less-than-comparable","Prague","|Complete|","17.0"
"`3348 <https://wg21.link/LWG3348>`__","``__cpp_lib_unwrap_ref``\ in wrong header","Prague","|Complete|","12.0"
"`3349 <https://wg21.link/LWG3349>`__","Missing ``__cpp_lib_constexpr_complex``\ for P0415R1","Prague","|Complete|","16.0"
"`3350 <https://wg21.link/LWG3350>`__","Simplify return type of ``lexicographical_compare_three_way``\ ","Prague","|Complete|","17.0","|spaceship|"
diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 3eecc354b811..6dd14bdd09db 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -35,7 +35,8 @@ Section,Description,Dependencies,Assignee,Complete
| `[stacktrace.basic.cmp] <https://wg21.link/stacktrace.basic.cmp>`_,| `basic_stacktrace <https://reviews.llvm.org/D123228>`_,[alg.three.way],Nikolas Klauser,|In Progress|
| `[string.cmp] <https://wg21.link/string.cmp>`_,| `basic_string <https://reviews.llvm.org/D131421>`_,None,Mark de Wever,|Complete|
| `[string.view.comparison] <https://wg21.link/string.view.comparison>`_,| `basic_string_view <https://reviews.llvm.org/D130295>`_,None,Mark de Wever,|Complete|
-| `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `array <https://reviews.llvm.org/D132265>`_,[expos.only.func],Adrian Vogelsgesang,|In Progress|
+| `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `array <https://reviews.llvm.org/D132265>`_,[expos.only.func],"| Adrian Vogelsgesang
+| Hristo Hristov",|Complete|
| `[deque.syn] <https://wg21.link/deque.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `deque <https://reviews.llvm.org/D144821>`_,[expos.only.func],Hristo Hristov,|Complete|
| `[forward.list.syn] <https://wg21.link/forward.list.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `forward_list <https://reviews.llvm.org/D145172>`_,[expos.only.func],Hristo Hristov,|Complete|
| `[list.syn] <https://wg21.link/list.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `list <https://reviews.llvm.org/D132312>`_,[expos.only.func],Adrian Vogelsgesang,|Complete|
diff --git a/libcxx/include/array b/libcxx/include/array
index 58e0fb273f01..5a8a1acca475 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -77,15 +77,18 @@ template <class T, class... U>
template <class T, size_t N>
bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
- bool operator!=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+ bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
template <class T, size_t N>
- bool operator<(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+ bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20
template <class T, size_t N>
- bool operator>(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+ bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20
template <class T, size_t N>
- bool operator<=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+ bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
template <class T, size_t N>
- bool operator>=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+ bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+template<class T, size_t N>
+ constexpr synth-three-way-result<T>
+ operator<=>(const array<T, N>& x, const array<T, N>& y); // since C++20
template <class T, size_t N >
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20
@@ -111,6 +114,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
#include <__algorithm/equal.h>
#include <__algorithm/fill_n.h>
#include <__algorithm/lexicographical_compare.h>
+#include <__algorithm/lexicographical_compare_three_way.h>
#include <__algorithm/swap_ranges.h>
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
@@ -401,47 +405,44 @@ operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
return _VSTD::equal(__x.begin(), __x.end(), __y.begin());
}
+#if _LIBCPP_STD_VER <= 17
+
template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
-{
+inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
return !(__x == __y);
}
template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
-{
- return _VSTD::lexicographical_compare(__x.begin(), __x.end(),
- __y.begin(), __y.end());
+inline _LIBCPP_HIDE_FROM_ABI bool operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
+ return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
}
template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
-{
+inline _LIBCPP_HIDE_FROM_ABI bool operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
return __y < __x;
}
template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
-{
+inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
return !(__y < __x);
}
template <class _Tp, size_t _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
-{
+inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
return !(__x < __y);
}
+#else // _LIBCPP_STD_VER <= 17
+
+template <class _Tp, size_t _Size>
+_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
+operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
+ return std::lexicographical_compare_three_way(
+ __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
+}
+
+#endif // _LIBCPP_STD_VER <= 17
+
template <class _Tp, size_t _Size>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
__enable_if_t<_Size == 0 || __is_swappable<_Tp>::value, void>
diff --git a/libcxx/test/std/containers/sequences/array/compare.fail.cpp b/libcxx/test/std/containers/sequences/array/compare.fail.cpp
deleted file mode 100644
index 1fe4c706b62c..000000000000
--- a/libcxx/test/std/containers/sequences/array/compare.fail.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <array>
-
-// bool operator==(array<T, N> const&, array<T, N> const&);
-// bool operator!=(array<T, N> const&, array<T, N> const&);
-// bool operator<(array<T, N> const&, array<T, N> const&);
-// bool operator<=(array<T, N> const&, array<T, N> const&);
-// bool operator>(array<T, N> const&, array<T, N> const&);
-// bool operator>=(array<T, N> const&, array<T, N> const&);
-
-
-#include <array>
-#include <vector>
-#include <cassert>
-
-#include "test_macros.h"
-
-template <class Array>
-void test_compare(const Array& LHS, const Array& RHS) {
- typedef std::vector<typename Array::value_type> Vector;
- const Vector LHSV(LHS.begin(), LHS.end());
- const Vector RHSV(RHS.begin(), RHS.end());
- assert((LHS == RHS) == (LHSV == RHSV));
- assert((LHS != RHS) == (LHSV != RHSV));
- assert((LHS < RHS) == (LHSV < RHSV));
- assert((LHS <= RHS) == (LHSV <= RHSV));
- assert((LHS > RHS) == (LHSV > RHSV));
- assert((LHS >= RHS) == (LHSV >= RHSV));
-}
-
-template <int Dummy> struct NoCompare {};
-
-int main(int, char**)
-{
- {
- typedef NoCompare<0> T;
- typedef std::array<T, 3> C;
- C c1 = {{}};
- // expected-error@*:* 2 {{invalid operands to binary expression}}
- TEST_IGNORE_NODISCARD (c1 == c1);
- TEST_IGNORE_NODISCARD (c1 < c1);
- }
- {
- typedef NoCompare<1> T;
- typedef std::array<T, 3> C;
- C c1 = {{}};
- // expected-error@*:* 2 {{invalid operands to binary expression}}
- TEST_IGNORE_NODISCARD (c1 != c1);
- TEST_IGNORE_NODISCARD (c1 > c1);
- }
- {
- typedef NoCompare<2> T;
- typedef std::array<T, 0> C;
- C c1 = {{}};
- // expected-error@*:* 2 {{invalid operands to binary expression}}
- TEST_IGNORE_NODISCARD (c1 == c1);
- TEST_IGNORE_NODISCARD (c1 < c1);
- }
-
- return 0;
-}
diff --git a/libcxx/test/std/containers/sequences/array/compare.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.pass.cpp
index 972600992980..f79a638c5688 100644
--- a/libcxx/test/std/containers/sequences/array/compare.pass.cpp
+++ b/libcxx/test/std/containers/sequences/array/compare.pass.cpp
@@ -8,13 +8,18 @@
// <array>
-// bool operator==(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-// bool operator!=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-// bool operator<(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-// bool operator<=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-// bool operator>(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-// bool operator>=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
-
+// template <class T, size_t N>
+// bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+// template <class T, size_t N>
+// bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
#include <array>
#include <cassert>
@@ -22,49 +27,53 @@
#include "test_macros.h"
#include "test_comparisons.h"
-TEST_CONSTEXPR_CXX20 bool tests()
-{
- {
- typedef std::array<int, 3> C;
- const C c1 = {1, 2, 3};
- const C c2 = {1, 2, 3};
- const C c3 = {3, 2, 1};
- const C c4 = {1, 2, 1};
- assert(testComparisons(c1, c2, true, false));
- assert(testComparisons(c1, c3, false, true));
- assert(testComparisons(c1, c4, false, false));
- }
- {
- typedef std::array<int, 0> C;
- const C c1 = {};
- const C c2 = {};
- assert(testComparisons(c1, c2, true, false));
- }
- {
- typedef std::array<LessAndEqComp, 3> C;
- const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)};
- const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)};
- const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)};
- const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
- assert(testComparisons(c1, c2, true, false));
- assert(testComparisons(c1, c3, false, true));
- assert(testComparisons(c1, c4, false, false));
- }
- {
- typedef std::array<LessAndEqComp, 0> C;
- const C c1 = {};
- const C c2 = {};
- assert(testComparisons(c1, c2, true, false));
- }
+TEST_CONSTEXPR_CXX20 bool tests() {
+ // Arrays where the elements support all comparison operators
+ AssertComparisonsReturnBool<std::array<int, 3> >();
+ {
+ typedef std::array<int, 3> C;
+ const C c1 = {1, 2, 3};
+ const C c2 = {1, 2, 3};
+ const C c3 = {3, 2, 1};
+ const C c4 = {1, 2, 1};
+ assert(testComparisons(c1, c2, true, false));
+ assert(testComparisons(c1, c3, false, true));
+ assert(testComparisons(c1, c4, false, false));
+ }
+ // Empty array
+ {
+ typedef std::array<int, 0> C;
+ const C c1 = {};
+ const C c2 = {};
+ assert(testComparisons(c1, c2, true, false));
+ }
+ // Arrays where the elements support only less and equality comparisons
+ AssertComparisonsReturnBool<std::array<LessAndEqComp, 3> >();
+ {
+ typedef std::array<LessAndEqComp, 3> C;
+ const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)};
+ const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)};
+ const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)};
+ const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
+ assert(testComparisons(c1, c2, true, false));
+ assert(testComparisons(c1, c3, false, true));
+ assert(testComparisons(c1, c4, false, false));
+ }
+ // Empty array where the elements support only less and equality comparisons
+ {
+ typedef std::array<LessAndEqComp, 0> C;
+ const C c1 = {};
+ const C c2 = {};
+ assert(testComparisons(c1, c2, true, false));
+ }
- return true;
+ return true;
}
-int main(int, char**)
-{
- tests();
+int main(int, char**) {
+ tests();
#if TEST_STD_VER >= 20
- static_assert(tests(), "");
+ static_assert(tests());
#endif
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp
new file mode 100644
index 000000000000..01be1db73041
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <array>
+
+// template<class T, size_t N>
+// constexpr synth-three-way-result<T>
+// operator<=>(const array<T, N>& x, const array<T, N>& y);
+
+#include <array>
+#include <cassert>
+
+#include "test_comparisons.h"
+
+// SFINAE
+
+constexpr std::size_t N{1};
+
+// The container should fulfill `std::three_way_comparable`
+static_assert(std::three_way_comparable<std::array<int, N>>);
+
+// Thanks to SFINAE, the following is not a compiler error but returns `false`
+struct NonComparable {};
+static_assert(!std::three_way_comparable<std::array<NonComparable, N>>);
+
+// Implementation detail of `test_sequence_container_array_spaceship`
+template <typename Elem, typename Order>
+constexpr void test_sequence_container_array_spaceship_with_type() {
+ // Empty containers
+ {
+ std::array<Elem, 0> l1 = {};
+ std::array<Elem, 0> l2 = {};
+ assert(testOrder(l1, l2, Order::equivalent));
+ }
+ // Identical contents
+ {
+ std::array l1{Elem{1}, Elem{1}};
+ std::array l2{Elem{1}, Elem{1}};
+ assert(testOrder(l1, l2, Order::equivalent));
+ }
+ // Less, due to contained values
+ {
+ std::array l1{Elem{1}, Elem{1}};
+ std::array l2{Elem{1}, Elem{2}};
+ assert(testOrder(l1, l2, Order::less));
+ }
+ // Greater, due to contained values
+ {
+ std::array l1{Elem{1}, Elem{3}};
+ std::array l2{Elem{1}, Elem{2}};
+ assert(testOrder(l1, l2, Order::greater));
+ }
+ // Shorter list - unsupported - containers must be of equal lengths
+ // Longer list - unsupported - containers must be of equal lengths
+ // Unordered
+ if constexpr (std::is_same_v<Elem, PartialOrder>) {
+ std::array l1{Elem{1}, Elem{std::numeric_limits<int>::min()}};
+ std::array l2{Elem{1}, Elem{2}};
+ assert(testOrder(l1, l2, Order::unordered));
+ }
+}
+
+// Tests the `operator<=>` on sequence containers `array`
+constexpr bool test_sequence_container_array_spaceship() {
+ // Test different comparison categories
+ test_sequence_container_array_spaceship_with_type<int, std::strong_ordering>();
+ test_sequence_container_array_spaceship_with_type<StrongOrder, std::strong_ordering>();
+ test_sequence_container_array_spaceship_with_type<WeakOrder, std::weak_ordering>();
+ test_sequence_container_array_spaceship_with_type<PartialOrder, std::partial_ordering>();
+
+ // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
+ test_sequence_container_array_spaceship_with_type<LessAndEqComp, std::weak_ordering>();
+
+ return true;
+}
+
+int main(int, char**) {
+ assert(test_sequence_container_array_spaceship());
+ static_assert(test_sequence_container_array_spaceship());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp b/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp
new file mode 100644
index 000000000000..b7267ec9b932
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <array>
+
+// template<class T, size_t N>
+// constexpr synth-three-way-result<T>
+// operator<=>(const array<T, N>& x, const array<T, N>& y);
+
+// arrays with different sizes should not compare
+
+#include <array>
+
+int main(int, char**) {
+ {
+ std::array a1{1};
+ std::array a2{1, 2};
+
+ // expected-error@*:* {{invalid operands to binary expression}}
+ a1 <=> a2;
+ }
+ {
+ std::array a1{1, 2};
+ std::array a2{1};
+
+ // expected-error@*:* {{invalid operands to binary expression}}
+ a1 <=> a2;
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/array/compare.verify.cpp b/libcxx/test/std/containers/sequences/array/compare.verify.cpp
new file mode 100644
index 000000000000..4b001601a4fe
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/compare.verify.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <array>
+
+// template <class T, size_t N>
+// bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
+// template <class T, size_t N>
+// bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+// template <class T, size_t N>
+// bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
+
+#include <array>
+
+#include "test_macros.h"
+
+template <int>
+struct NoCompare {};
+
+int main(int, char**) {
+ {
+ typedef NoCompare<0> T;
+ typedef std::array<T, 3> C;
+ C c1 = {{}};
+ // expected-error@*:* 2 {{invalid operands to binary expression}}
+ TEST_IGNORE_NODISCARD(c1 == c1);
+ TEST_IGNORE_NODISCARD(c1 < c1);
+ }
+ {
+ typedef NoCompare<1> T;
+ typedef std::array<T, 3> C;
+ C c1 = {{}};
+ // expected-error@*:* 2 {{invalid operands to binary expression}}
+ TEST_IGNORE_NODISCARD(c1 != c1);
+ TEST_IGNORE_NODISCARD(c1 > c1);
+ }
+ {
+ typedef NoCompare<2> T;
+ typedef std::array<T, 0> C;
+ C c1 = {{}};
+ // expected-error@*:* 2 {{invalid operands to binary expression}}
+ TEST_IGNORE_NODISCARD(c1 == c1);
+ TEST_IGNORE_NODISCARD(c1 < c1);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/support/test_container_comparisons.h b/libcxx/test/support/test_container_comparisons.h
index 561275c8bb79..f9dae9d6455a 100644
--- a/libcxx/test/support/test_container_comparisons.h
+++ b/libcxx/test/support/test_container_comparisons.h
@@ -62,7 +62,7 @@ constexpr void test_sequence_container_spaceship_with_type() {
// Tests the `operator<=>` on sequence containers
template <template <typename...> typename Container>
constexpr bool test_sequence_container_spaceship() {
- // The container should fulfil `std::three_way_comparable`
+ // The container should fulfill `std::three_way_comparable`
static_assert(std::three_way_comparable<Container<int>>);
// Test different comparison categories
@@ -71,7 +71,7 @@ constexpr bool test_sequence_container_spaceship() {
test_sequence_container_spaceship_with_type<Container, WeakOrder, std::weak_ordering>();
test_sequence_container_spaceship_with_type<Container, PartialOrder, std::partial_ordering>();
- // `LessAndEqComp` does not have `operator<=>`. ordering is sythesized based on `operator<`
+ // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
test_sequence_container_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>();
// Thanks to SFINAE, the following is not a compiler error but returns `false`
@@ -186,7 +186,7 @@ constexpr void test_ordered_map_container_spaceship_with_type() {
// Tests the `operator<=>` on ordered containers
template <template <typename...> typename Container>
constexpr bool test_ordered_map_container_spaceship() {
- // The container should fulfil `std::three_way_comparable`
+ // The container should fulfill `std::three_way_comparable`
static_assert(std::three_way_comparable<Container<int, int>>);
// Test different comparison categories
@@ -195,7 +195,7 @@ constexpr bool test_ordered_map_container_spaceship() {
test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>();
test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>();
- // `LessAndEqComp` does not have `operator<=>`. ordering is sythesized based on `operator<`
+ // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<`
test_ordered_map_container_spaceship_with_type<Container, int, LessAndEqComp, std::weak_ordering>();
// Thanks to SFINAE, the following is not a compiler error but returns `false`