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