1 // RUN: %clang_cc1 -std=c++2a -verify %s 2 3 // expected-no-diagnostics 4 namespace std { 5 struct strong_ordering { 6 int n; 7 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; 17 constexpr void add(char c) { buff[n++] = c; } 18 constexpr bool operator==(const char *p) const { return __builtin_strcmp(p, buff) == 0; } 19 }; 20 21 template<char C> struct B { 22 Log *log; 23 constexpr bool operator==(const B&) const { log->add(C); return true; } 24 constexpr std::strong_ordering operator<=>(const B&) const { log->add(C); return {0}; } 25 }; 26 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 40 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 53 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