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