summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/class/class.compare/class.spaceship/p2.cpp')
-rw-r--r--clang/test/CXX/class/class.compare/class.spaceship/p2.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
new file mode 100644
index 00000000000..1290a063e79
--- /dev/null
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+namespace std {
+ class strong_ordering {
+ int n;
+ constexpr strong_ordering(int n) : n(n) {}
+ public:
+ static const strong_ordering less, equal, greater;
+ bool operator!=(int) { return n != 0; }
+ };
+ constexpr strong_ordering strong_ordering::less{-1},
+ strong_ordering::equal{0}, strong_ordering::greater{1};
+
+ class weak_ordering {
+ int n;
+ constexpr weak_ordering(int n) : n(n) {}
+ public:
+ constexpr weak_ordering(strong_ordering o);
+ static const weak_ordering less, equivalent, greater;
+ bool operator!=(int) { return n != 0; }
+ };
+ constexpr weak_ordering weak_ordering::less{-1},
+ weak_ordering::equivalent{0}, weak_ordering::greater{1};
+
+ class partial_ordering {
+ int n;
+ constexpr partial_ordering(int n) : n(n) {}
+ public:
+ constexpr partial_ordering(strong_ordering o);
+ constexpr partial_ordering(weak_ordering o);
+ static const partial_ordering less, equivalent, greater, unordered;
+ bool operator!=(int) { return n != 0; }
+ };
+ constexpr partial_ordering partial_ordering::less{-1},
+ partial_ordering::equivalent{0}, partial_ordering::greater{1},
+ partial_ordering::unordered{2};
+}
+
+namespace DeducedNotCat {
+ struct A {
+ A operator<=>(const A&) const; // expected-note {{selected 'operator<=>' for member 'a' declared here}}
+ };
+ struct B {
+ A a; // expected-note {{return type 'DeducedNotCat::A' of three-way comparison for member 'a' is not a standard comparison category type}}
+ auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
+ };
+}
+
+namespace DeducedVsSynthesized {
+ struct A {
+ bool operator==(const A&) const;
+ bool operator<(const A&) const;
+ };
+ struct B {
+ A a; // expected-note {{no viable comparison function for member 'a'}}
+ auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
+ };
+}
+
+namespace Deduction {
+ template<typename T> struct wrap {
+ T t;
+ friend auto operator<=>(const wrap&, const wrap&) = default;
+ };
+
+ using strong = wrap<int>;
+ using strong2 = wrap<int*>;
+ struct weak {
+ friend std::weak_ordering operator<=>(weak, weak);
+ };
+ using partial = wrap<float>;
+
+ template<typename ...T> struct A : T... {
+ friend auto operator<=>(const A&, const A&) = default;
+ };
+
+ template<typename Expected, typename ...Ts> void f() {
+ using T = Expected; // expected-note {{previous}}
+ using T = decltype(A<Ts...>() <=> A<Ts...>()); // expected-error {{different type}}
+ void(A<Ts...>() <=> A<Ts...>()); // trigger synthesis of body
+ }
+
+ template void f<std::strong_ordering>();
+ template void f<std::strong_ordering, strong>();
+ template void f<std::strong_ordering, strong, strong2>();
+
+ template void f<std::weak_ordering, weak>();
+ template void f<std::weak_ordering, weak, strong>();
+ template void f<std::weak_ordering, strong, weak>();
+
+ template void f<std::partial_ordering, partial>();
+ template void f<std::partial_ordering, weak, partial>();
+ template void f<std::partial_ordering, strong, partial>();
+ template void f<std::partial_ordering, partial, weak>();
+ template void f<std::partial_ordering, partial, strong>();
+ template void f<std::partial_ordering, weak, partial, strong>();
+
+ // Check that the above mechanism works.
+ template void f<std::strong_ordering, weak>(); // expected-note {{instantiation of}}
+}
+
+namespace BadDeducedType {
+ struct A {
+ // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'auto &'}}
+ friend auto &operator<=>(const A&, const A&) = default;
+ };
+
+ struct B {
+ // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'const auto'}}
+ friend const auto operator<=>(const B&, const B&) = default;
+ };
+
+ template<typename T> struct X {}; // expected-note {{here}}
+ struct C {
+ // expected-error@+1 {{deduction not allowed in function return type}}
+ friend X operator<=>(const C&, const C&) = default;
+ };
+
+ template<typename T> concept CmpCat = true;
+ struct D {
+ // FIXME: Once we support P1141R2, we should give a better diagnostic here:
+ // {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'CmpCat auto'}}
+ friend CmpCat auto operator<=>(const D&, const D&) = default; // expected-error {{unknown type name 'CmpCat'}}
+ };
+}
OpenPOWER on IntegriCloud