xref: /llvm-project/clang/test/CXX/class/class.compare/class.compare.default/p5.cpp (revision e6e6e34b95cfe03275943fde0db259cc7d57f4ad)
1cafc7416SRichard Smith // RUN: %clang_cc1 -std=c++2a -verify %s
2cafc7416SRichard Smith 
3cafc7416SRichard Smith // expected-no-diagnostics
4cafc7416SRichard Smith namespace std {
5cafc7416SRichard Smith   struct strong_ordering {
6cafc7416SRichard Smith     int n;
operator intstd::strong_ordering7cafc7416SRichard Smith     constexpr operator int() const { return n; }
8cafc7416SRichard Smith     static const strong_ordering less, equal, greater;
9cafc7416SRichard Smith   };
10cafc7416SRichard Smith   constexpr strong_ordering strong_ordering::less{-1}, strong_ordering::equal{0}, strong_ordering::greater{1};
11cafc7416SRichard Smith }
12cafc7416SRichard Smith 
13cafc7416SRichard Smith // Check that we compare subobjects in the right order.
14cafc7416SRichard Smith struct Log {
15*e6e6e34bSRichard Smith   char buff[10] = {};
16cafc7416SRichard Smith   int n = 0;
addLog17cafc7416SRichard Smith   constexpr void add(char c) { buff[n++] = c; }
operator ==Log18cafc7416SRichard Smith   constexpr bool operator==(const char *p) const { return __builtin_strcmp(p, buff) == 0; }
19cafc7416SRichard Smith };
20cafc7416SRichard Smith 
21cafc7416SRichard Smith template<char C> struct B {
22cafc7416SRichard Smith   Log *log;
operator ==B23cafc7416SRichard Smith   constexpr bool operator==(const B&) const { log->add(C); return true; }
operator <=>B24cafc7416SRichard Smith   constexpr std::strong_ordering operator<=>(const B&) const { log->add(C); return {0}; }
25cafc7416SRichard Smith };
26cafc7416SRichard Smith 
check(bool which,const char * str)27*e6e6e34bSRichard Smith template<typename T> constexpr bool check(bool which, const char *str) {
28*e6e6e34bSRichard Smith   Log log;
29*e6e6e34bSRichard Smith   T c(&log);
30*e6e6e34bSRichard Smith   (void)(which ? c == c : c <=> c);
31*e6e6e34bSRichard Smith   return log == str;
32*e6e6e34bSRichard Smith }
33cafc7416SRichard Smith 
34*e6e6e34bSRichard Smith struct C : B<'a'>, B<'b'> {
35*e6e6e34bSRichard Smith   B<'r'> r[3];
36*e6e6e34bSRichard Smith   B<'c'> c;
37*e6e6e34bSRichard Smith   B<'s'> s[2];
38*e6e6e34bSRichard Smith   B<'d'> d;
39*e6e6e34bSRichard Smith 
CC40*e6e6e34bSRichard Smith   constexpr C(Log *p) : B<'a'>{p}, B<'b'>{p}, r{p, p, p}, c{p}, s{p, p}, d{p} {}
41cafc7416SRichard Smith 
42cafc7416SRichard Smith   bool operator==(const C&) const = default;
43cafc7416SRichard Smith   std::strong_ordering operator<=>(const C&) const = default;
44cafc7416SRichard Smith };
45cafc7416SRichard Smith 
46*e6e6e34bSRichard Smith static_assert(check<C>(false, "abrrrcssd"));
47*e6e6e34bSRichard Smith static_assert(check<C>(true, "abrrrcssd"));
48*e6e6e34bSRichard Smith 
49*e6e6e34bSRichard Smith struct D {
50*e6e6e34bSRichard Smith   B<'x'> x;
51*e6e6e34bSRichard Smith   B<'y'> y[2];
52*e6e6e34bSRichard Smith 
DD53*e6e6e34bSRichard Smith   constexpr D(Log *p) : x{p}, y{p, p} {}
54*e6e6e34bSRichard Smith 
55*e6e6e34bSRichard Smith   bool operator==(const D&) const = default;
56*e6e6e34bSRichard Smith   std::strong_ordering operator<=>(const D&) const = default;
57*e6e6e34bSRichard Smith };
58*e6e6e34bSRichard Smith 
59*e6e6e34bSRichard Smith static_assert(check<D>(false, "xyy"));
60*e6e6e34bSRichard Smith static_assert(check<D>(true, "xyy"));
61