// RUN: %clang_cc1 -std=c++2a -verify %s template struct Op { L l; const char *op; R r; }; // FIXME: Remove once we implement P1816R0. template Op(L, R) -> Op; struct A {}; struct B {}; constexpr Op operator<=>(A a, B b) { return {a, "<=>", b}; } template constexpr Op, V> operator< (Op a, V b) { return {a, "<", b}; } template constexpr Op, V> operator<= (Op a, V b) { return {a, "<=", b}; } template constexpr Op, V> operator> (Op a, V b) { return {a, ">", b}; } template constexpr Op, V> operator>= (Op a, V b) { return {a, ">=", b}; } template constexpr Op, V> operator<=>(Op a, V b) { return {a, "<=>", b}; } template constexpr Op> operator< (T a, Op b) { return {a, "<", b}; } template constexpr Op> operator<= (T a, Op b) { return {a, "<=", b}; } template constexpr Op> operator> (T a, Op b) { return {a, ">", b}; } template constexpr Op> operator>= (T a, Op b) { return {a, ">=", b}; } template constexpr Op> operator<=>(T a, Op b) { return {a, "<=>", b}; } constexpr bool same(A, A) { return true; } constexpr bool same(B, B) { return true; } constexpr bool same(int a, int b) { return a == b; } template constexpr bool same(Op x, Op y) { return same(x.l, y.l) && __builtin_strcmp(x.op, y.op) == 0 && same(x.r, y.r); } // x @ y is interpreted as: void f(A x, B y) { // -- (x <=> y) @ 0 if not reversed static_assert(same(x < y, (x <=> y) < 0)); static_assert(same(x <= y, (x <=> y) <= 0)); static_assert(same(x > y, (x <=> y) > 0)); static_assert(same(x >= y, (x <=> y) >= 0)); static_assert(same(x <=> y, x <=> y)); // (not rewritten) } void g(B x, A y) { // -- 0 @ (y <=> x) if reversed static_assert(same(x < y, 0 < (y <=> x))); static_assert(same(x <= y, 0 <= (y <=> x))); static_assert(same(x > y, 0 > (y <=> x))); static_assert(same(x >= y, 0 >= (y <=> x))); static_assert(same(x <=> y, 0 <=> (y <=> x))); } // We can rewrite into a call involving a builtin operator. struct X { int result; }; struct Y {}; constexpr int operator<=>(X x, Y) { return x.result; } static_assert(X{-1} < Y{}); static_assert(X{0} < Y{}); // expected-error {{failed}} static_assert(X{0} <= Y{}); static_assert(X{1} <= Y{}); // expected-error {{failed}} static_assert(X{1} > Y{}); static_assert(X{0} > Y{}); // expected-error {{failed}} static_assert(X{0} >= Y{}); static_assert(X{-1} >= Y{}); // expected-error {{failed}} static_assert(Y{} < X{1}); static_assert(Y{} < X{0}); // expected-error {{failed}} static_assert(Y{} <= X{0}); static_assert(Y{} <= X{-1}); // expected-error {{failed}} static_assert(Y{} > X{-1}); static_assert(Y{} > X{0}); // expected-error {{failed}} static_assert(Y{} >= X{0}); static_assert(Y{} >= X{1}); // expected-error {{failed}}