xref: /llvm-project/clang/test/CXX/class/class.compare/class.rel/p2.cpp (revision 1376c73927dcb899db5d46f7b970692e2e95f9ac)
15253d913SRichard Smith // RUN: %clang_cc1 -std=c++2a -verify %s
25253d913SRichard Smith 
35253d913SRichard Smith namespace Rel {
45253d913SRichard Smith   struct A {
5cafc7416SRichard Smith     int n;
operator <=>Rel::A6cafc7416SRichard Smith     constexpr int operator<=>(A a) const { return n - a.n; }
75253d913SRichard Smith     friend bool operator<(const A&, const A&) = default;
85253d913SRichard Smith     friend bool operator<=(const A&, const A&) = default;
95253d913SRichard Smith     friend bool operator>(const A&, const A&) = default;
105253d913SRichard Smith     friend bool operator>=(const A&, const A&) = default;
115253d913SRichard Smith   };
12cafc7416SRichard Smith   static_assert(A{0} < A{1});
13cafc7416SRichard Smith   static_assert(A{1} < A{1}); // expected-error {{failed}}
14cafc7416SRichard Smith   static_assert(A{0} <= A{1});
15cafc7416SRichard Smith   static_assert(A{1} <= A{1});
16cafc7416SRichard Smith   static_assert(A{2} <= A{1}); // expected-error {{failed}}
17cafc7416SRichard Smith   static_assert(A{1} > A{0});
18cafc7416SRichard Smith   static_assert(A{1} > A{1}); // expected-error {{failed}}
19cafc7416SRichard Smith   static_assert(A{1} >= A{0});
20cafc7416SRichard Smith   static_assert(A{1} >= A{1});
21cafc7416SRichard Smith   static_assert(A{1} >= A{2}); // expected-error {{failed}}
225253d913SRichard Smith 
235253d913SRichard Smith   struct B {
245253d913SRichard Smith     bool operator<=>(B) const = delete; // expected-note 4{{deleted here}} expected-note-re 8{{candidate {{.*}} deleted}}
25*1376c739SNathan James     friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
26*1376c739SNathan James     friend bool operator<=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
27*1376c739SNathan James     friend bool operator>(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
28*1376c739SNathan James     friend bool operator>=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
295253d913SRichard Smith   };
305253d913SRichard Smith   bool b1 = B() < B(); // expected-error {{deleted}}
315253d913SRichard Smith   bool b2 = B() <= B(); // expected-error {{deleted}}
325253d913SRichard Smith   bool b3 = B() > B(); // expected-error {{deleted}}
335253d913SRichard Smith   bool b4 = B() >= B(); // expected-error {{deleted}}
345253d913SRichard Smith 
355253d913SRichard Smith   struct C {
365253d913SRichard Smith     friend bool operator<=>(const C&, const C&);
375253d913SRichard Smith     friend bool operator<(const C&, const C&); // expected-note {{because this non-rewritten comparison function would be the best match}}
385253d913SRichard Smith 
39*1376c739SNathan James     bool operator<(const C&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
405253d913SRichard Smith     bool operator>(const C&) const = default; // OK
415253d913SRichard Smith   };
425253d913SRichard Smith }
435253d913SRichard Smith 
445253d913SRichard Smith // Under P2002R0, operator!= follows these rules too.
455253d913SRichard Smith namespace NotEqual {
465253d913SRichard Smith   struct A {
47cafc7416SRichard Smith     int n;
operator ==NotEqual::A48cafc7416SRichard Smith     constexpr bool operator==(A a) const { return n == a.n; }
495253d913SRichard Smith     friend bool operator!=(const A&, const A&) = default;
505253d913SRichard Smith   };
51cafc7416SRichard Smith   static_assert(A{1} != A{2});
52cafc7416SRichard Smith   static_assert(A{1} != A{1}); // expected-error {{failed}}
535253d913SRichard Smith 
545253d913SRichard Smith   struct B {
555253d913SRichard Smith     bool operator==(B) const = delete; // expected-note {{deleted here}} expected-note-re 2{{candidate {{.*}} deleted}}
56*1376c739SNathan James     friend bool operator!=(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note {{because it would invoke a deleted comparison}} expected-note-re {{candidate {{.*}} deleted}} expected-note{{replace 'default'}}
575253d913SRichard Smith   };
585253d913SRichard Smith   bool b = B() != B(); // expected-error {{deleted}}
595253d913SRichard Smith 
605253d913SRichard Smith   struct C {
615253d913SRichard Smith     friend bool operator==(const C&, const C&);
625253d913SRichard Smith     friend bool operator!=(const C&, const C&); // expected-note {{because this non-rewritten comparison function would be the best match}}
635253d913SRichard Smith 
64*1376c739SNathan James     bool operator!=(const C&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
655253d913SRichard Smith   };
665253d913SRichard Smith 
675253d913SRichard Smith   // Ensure we don't go into an infinite loop diagnosing this: the first function
685253d913SRichard Smith   // is deleted because it calls the second function, which is deleted because it
695253d913SRichard Smith   // calls the first.
705253d913SRichard Smith   struct Evil {
71*1376c739SNathan James     friend bool operator!=(const Evil&, const Evil&) = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}} expected-note{{replace 'default'}}
72*1376c739SNathan James     bool operator!=(const Evil&) const = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}} expected-note{{replace 'default'}}
735253d913SRichard Smith   };
745253d913SRichard Smith }
758e0c9e21SRichard Smith 
768e0c9e21SRichard Smith namespace Access {
778e0c9e21SRichard Smith   class A {
788e0c9e21SRichard Smith     int operator<=>(A) const; // expected-note {{private}}
798e0c9e21SRichard Smith   };
808e0c9e21SRichard Smith   struct B : A {
81*1376c739SNathan James     friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
828e0c9e21SRichard Smith     // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because it would invoke a private 'operator<=>' member of 'Access::A'}}
838e0c9e21SRichard Smith   };
848e0c9e21SRichard Smith }
85