aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/c-c++-common/cpp/spaceship-1.c6
-rw-r--r--gcc/testsuite/g++.dg/cpp/spaceship-1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq1.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq1a.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq4.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq5.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq6.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-eq7.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-err1.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-err2.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C93
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C41
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-scalar2.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae1.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth1.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth1a.C113
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth2.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth3.C48
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth3a.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-weak1.C15
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr21802.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb22.C7
27 files changed, 658 insertions, 6 deletions
diff --git a/gcc/testsuite/c-c++-common/cpp/spaceship-1.c b/gcc/testsuite/c-c++-common/cpp/spaceship-1.c
new file mode 100644
index 0000000..a3dc38d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/spaceship-1.c
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11" { target c } } */
+
+#define A(x, y) x##y
+A(<=, >) /* { dg-error "does not give a valid preprocessing token" "" { target { ! c++2a } } } */
+A(<=>, >) /* { dg-error "does not give a valid preprocessing token" "" { target c++2a } } */
diff --git a/gcc/testsuite/g++.dg/cpp/spaceship-1.C b/gcc/testsuite/g++.dg/cpp/spaceship-1.C
new file mode 100644
index 0000000..241b277
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/spaceship-1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++17_down } }
+// { dg-options "-Wno-pointer-arith" }
+
+struct X {};
+bool operator<= (X, X);
+template<bool (X, X)> struct Y {};
+Y<&operator<=> y;
+bool foo (bool (*fn) (X, X), int n) { return n+&operator<=> fn; }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
new file mode 100644
index 0000000..9d008f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++2a } }
+
+struct A
+{
+ int i;
+ bool operator==(A a) const { return i == a.i; }
+};
+
+struct B
+{
+ A a;
+ bool operator==(const B&) const = default; // { dg-error "A::operator==" }
+};
+
+constexpr bool x = B() == B(); // { dg-error "non-.constexpr" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1.C
new file mode 100644
index 0000000..19a03fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1.C
@@ -0,0 +1,17 @@
+// { dg-do run { target c++2a } }
+
+struct D
+{
+ int i;
+ bool operator==(const D& x) const = default; // OK, returns x.i == y.i
+ bool operator!=(const D& z) const = default; // OK, returns !(*this == z)
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+int main()
+{
+ D d{42};
+ assert (d == d);
+ assert (!(d != d));
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1a.C
new file mode 100644
index 0000000..7e98c47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq1a.C
@@ -0,0 +1,24 @@
+// { dg-do run { target c++2a } }
+
+template <class T>
+struct D
+{
+ T i;
+ bool operator==(const D& x) const = default; // OK, returns x.i == y.i
+ bool operator!=(const D& z) const = default; // OK, returns !(*this == z)
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+template <class T>
+void f()
+{
+ D<T> d{42};
+ assert (d == d);
+ assert (!(d != d));
+}
+
+int main()
+{
+ f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq2.C
new file mode 100644
index 0000000..06b988f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++2a } }
+
+struct D
+{
+ int i;
+ bool operator==(const D& x) const = default; // OK, returns x.i == y.i
+ bool operator!=(const D& z) const = default; // OK, returns !(*this == z)
+};
+
+constexpr D d{42};
+static_assert (d == d);
+static_assert (!(d != d));
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
new file mode 100644
index 0000000..490726d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++2a } }
+
+struct A {
+ bool operator==(const A&) const;
+};
+
+struct D
+{
+ A i;
+ bool operator==(const D& x) const = default; // { dg-error "A::operator==" }
+ bool operator!=(const D& z) const = default; // { dg-error "D::operator==" }
+};
+
+constexpr D d{A()};
+static_assert (d == d); // { dg-error "non-constant|constexpr" }
+static_assert (!(d != d)); // { dg-error "non-constant|constexpr" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq4.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq4.C
new file mode 100644
index 0000000..d89fc88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq4.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++2a } }
+
+struct A {
+ int operator==(const A&) const = default; // { dg-error "return .bool" }
+ bool operator==(const A&, const A&) const = default; // { dg-error "exactly one" }
+ bool operator==(int) const = default; // { dg-error "parameter type" }
+ bool operator==(const A&) = default; // { dg-error "const" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq5.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq5.C
new file mode 100644
index 0000000..ac24f36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq5.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++2a } }
+
+struct A {
+ int &r; // { dg-message "reference" }
+ bool operator==(const A&) const = default; // { dg-message "deleted" }
+};
+
+int i;
+A a { i };
+bool b = a == a; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq6.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq6.C
new file mode 100644
index 0000000..f804e13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq6.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++2a } }
+
+struct A
+{
+ union { int i; } // { dg-message "union" }
+ bool operator==(const A&) const = default; // { dg-message "deleted" }
+};
+
+A a { 42 };
+bool b = a == a; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq7.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq7.C
new file mode 100644
index 0000000..8112eaa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq7.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++2a } }
+
+union A
+{
+ int i;
+ bool operator==(const A&) const = default; // { dg-message "union" }
+};
+
+A a { 42 };
+bool b = a == a; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err1.C
new file mode 100644
index 0000000..ce7b56c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err1.C
@@ -0,0 +1,5 @@
+// Test that we suggest adding #include <compare>.
+// { dg-do compile { target c++2a } }
+
+auto x = 1<=>2; // { dg-error "" }
+// { dg-message "<compare>" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err2.C
new file mode 100644
index 0000000..6461c6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err2.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++2a } }
+
+#include <compare>
+template <class T, T x = (T() <=> T())> // { dg-error "31:0 <=> 0" }
+void f(T);
+//constexpr int f(...) { return 42; }
+constexpr int i = f(24); // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C
new file mode 100644
index 0000000..bb60302
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C
@@ -0,0 +1,15 @@
+// This should continue to work.
+// { dg-do compile { target c++2a } }
+
+template<class T>
+struct A {
+ template<class U>
+ bool operator==(const A<U>&);
+};
+
+int main()
+{
+ A<int> a1;
+ A<void> a2;
+ return a1 == a2;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C
new file mode 100644
index 0000000..2ca86b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C
@@ -0,0 +1,93 @@
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while(0)
+
+void f(){}
+void g(){}
+
+int main()
+{
+ {
+ constexpr auto v = 1 <=> 2;
+ static_assert (__is_same_as (decltype (v), const std::strong_ordering));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ static_assert (is_lt (v));
+ static_assert (is_lteq (v));
+ static_assert (!is_gt (v));
+ static_assert (!is_gteq (v));
+ }
+
+ {
+ enum E { a = 0 };
+ constexpr auto v = E::a <=> 1;
+ static_assert (__is_same_as (decltype (v), const std::strong_ordering));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ static_assert (is_lt (v));
+ static_assert (is_lteq (v));
+ static_assert (!is_gt (v));
+ static_assert (!is_gteq (v));
+ }
+
+ {
+ enum class E { a, b };
+ constexpr auto v = E::a <=> E::b;
+ static_assert (__is_same_as (decltype (v), const std::strong_ordering));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ static_assert (is_lt (v));
+ static_assert (is_lteq (v));
+ static_assert (!is_gt (v));
+ static_assert (!is_gteq (v));
+ }
+
+ {
+ int ar[2];
+ constexpr auto v = &ar[1] <=> &ar[0];
+ static_assert (__is_same_as (decltype (v), const std::strong_ordering));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ static_assert (!is_lt (v));
+ static_assert (!is_lteq (v));
+ static_assert (is_gt (v));
+ static_assert (is_gteq (v));
+ }
+
+ {
+ constexpr auto v = 3.14 <=> 3.14;
+ static_assert (__is_same_as (decltype (v), const std::partial_ordering));
+ static_assert (is_eq (v));
+ static_assert (!is_neq (v));
+ static_assert (!is_lt (v));
+ static_assert (is_lteq (v));
+ static_assert (!is_gt (v));
+ static_assert (is_gteq (v));
+ }
+
+ {
+ // GCC doesn't consider &f == &g to be a constant expression (PR 69681)
+ const auto v = &f <=> &g;
+ static_assert (__is_same_as (decltype (v), const std::strong_equality));
+ assert (!is_eq (v));
+ assert (is_neq (v));
+ }
+
+ {
+ struct A { int i; int j; };
+ constexpr auto v = &A::i <=> &A::j;
+ static_assert (__is_same_as (decltype (v), const std::strong_equality));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ }
+
+ {
+ struct A { void f(); };
+ constexpr auto v = &A::f <=> &A::f;
+ static_assert (__is_same_as (decltype (v), const std::strong_equality));
+ static_assert (is_eq (v));
+ static_assert (!is_neq (v));
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C
new file mode 100644
index 0000000..1dc9549
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C
@@ -0,0 +1,41 @@
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while(0)
+
+void f(){}
+void g(){}
+
+template <class T, class U, class R>
+constexpr bool check(T a, U b, R expected)
+{
+ auto r = a <=> b;
+ static_assert (__is_same_as (decltype (r), R));
+ return r == expected;
+}
+
+int main()
+{
+ static_assert (check (1, 2, std::strong_ordering::less));
+
+ enum E1 { a = 0 };
+ static_assert (check (a, 1, std::strong_ordering::less));
+
+ enum class E2 { a, b };
+ static_assert (check (E2::a, E2::b, std::strong_ordering::less));
+
+ int ar[2];
+ static_assert (check (&ar[1], &ar[0], std::strong_ordering::greater));
+
+ static_assert (check (3.14, 3.14, std::partial_ordering::equivalent));
+
+ // GCC doesn't consider &f == &g to be a constant expression (PR 69681)
+ assert (check (&f, &g, std::strong_equality::nonequal));
+
+ struct A { int i; int j; };
+ static_assert (check (&A::i, &A::j, std::strong_equality::nonequal));
+
+ struct A2 { void f(); };
+ static_assert (check (&A2::f, &A2::f, std::strong_equality::equal));
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar2.C
new file mode 100644
index 0000000..d3cb0a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar2.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++2a } }
+
+#include <compare>
+
+int main()
+{
+ { true <=> 1; } // { dg-error "bool" }
+ { int a[2]; a <=> a; } // { dg-error "2" }
+ { -1 <=> 1U; } // { dg-error "narrowing" }
+ { enum A { a }; enum B { b }; a <=> b; } // { dg-error "A" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C
new file mode 100644
index 0000000..20bc8e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C
@@ -0,0 +1,21 @@
+// { dg-do run { target c++2a } }
+// { dg-options "-fext-numeric-literals" }
+
+#include <compare>
+
+int main()
+{
+ // GCC complex literal extension
+ {
+ constexpr auto v = 1 <=> 1i;
+ static_assert (__is_same_as (decltype (v), const std::strong_equality));
+ static_assert (!is_eq (v));
+ static_assert (is_neq (v));
+ }
+ {
+ constexpr auto v = 1i <=> 1.0i;
+ static_assert (__is_same_as (decltype (v), const std::weak_equality));
+ static_assert (is_eq (v));
+ static_assert (!is_neq (v));
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae1.C
new file mode 100644
index 0000000..6a03f54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae1.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++2a } }
+
+// missing #include <compare>
+template <class T, T x = (T() <=> T()) == 0>
+void f(T);
+constexpr int f(...) { return 42; }
+constexpr int i = f(24);
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1.C
new file mode 100644
index 0000000..2a35de9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1.C
@@ -0,0 +1,43 @@
+// Test with all operators explicitly defaulted.
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+struct D
+{
+ int i;
+ auto operator<=>(const D& x) const = default;
+ bool operator==(const D& x) const = default;
+ bool operator!=(const D& x) const = default;
+ bool operator<(const D& x) const = default;
+ bool operator<=(const D& x) const = default;
+ bool operator>(const D& x) const = default;
+ bool operator>=(const D& x) const = default;
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+int main()
+{
+ D d{42};
+ D d2{24};
+
+ assert (is_eq (d <=> d));
+ assert (is_lteq (d <=> d));
+ assert (is_gteq (d <=> d));
+ assert (is_lt (d2 <=> d));
+ assert (is_lteq (d2 <=> d));
+ assert (is_gt (d <=> d2));
+ assert (is_gteq (d <=> d2));
+
+ assert (d == d);
+ assert (!(d2 == d));
+ assert (!(d == d2));
+ assert (d != d2);
+ assert (!(d2 != d2));
+
+ assert (d2 < d);
+ assert (d2 <= d);
+ assert (d > d2);
+ assert (d >= d2);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1a.C
new file mode 100644
index 0000000..3231457
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth1a.C
@@ -0,0 +1,113 @@
+// Test with all operators explicitly defaulted.
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+template <class T>
+struct D
+{
+ T i;
+ auto operator<=>(const D& x) const = default;
+ bool operator==(const D& x) const = default;
+ bool operator!=(const D& x) const = default;
+ bool operator<(const D& x) const = default;
+ bool operator<=(const D& x) const = default;
+ bool operator>(const D& x) const = default;
+ bool operator>=(const D& x) const = default;
+};
+
+template <class T>
+struct E
+{
+ T i;
+ auto operator<=>(const E& x) const = default;
+ // auto operator==(const E& x) const = default;
+ // auto operator!=(const E& x) const = default;
+ // auto operator<(const E& x) const = default;
+ // auto operator<=(const E& x) const = default;
+ // auto operator>(const E& x) const = default;
+ // auto operator>=(const E& x) const = default;
+};
+
+template <class T>
+struct F
+{
+ T i;
+ constexpr auto operator<=>(T x) const { return i<=>x; }
+ constexpr bool operator== (T x) const { return i==x; }
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+template <class T, class U>
+constexpr bool check_eq (T d, U d2)
+{
+ return is_eq (d <=> d2)
+ && is_eq (d2 <=> d)
+ && is_lteq (d <=> d2)
+ && is_lteq (d2 <=> d)
+ && !is_lt (d <=> d2)
+ && !is_lt (d2 <=> d)
+ && is_gteq (d <=> d2)
+ && is_gteq (d2 <=> d)
+ && !is_gt (d <=> d2)
+ && !is_gt (d2 <=> d)
+ && d == d2
+ && d2 == d
+ && !(d != d2)
+ && !(d2 != d)
+ && d >= d2
+ && d <= d2
+ && d2 >= d
+ && d2 <= d
+ && !(d < d2)
+ && !(d2 < d)
+ && !(d > d2)
+ && !(d2 > d);
+}
+
+template <class T, class U>
+constexpr bool check_less (T d, U d2)
+{
+ return !is_eq (d <=> d2)
+ && !is_eq (d2 <=> d)
+ && is_lteq (d <=> d2)
+ && !is_lteq (d2 <=> d)
+ && is_lt (d <=> d2)
+ && !is_lt (d2 <=> d)
+ && !is_gteq (d <=> d2)
+ && is_gteq (d2 <=> d)
+ && !is_gt (d <=> d2)
+ && is_gt (d2 <=> d)
+ && !(d == d2)
+ && !(d2 == d)
+ && (d != d2)
+ && (d2 != d)
+ && !(d >= d2)
+ && (d <= d2)
+ && (d2 >= d)
+ && !(d2 <= d)
+ && (d < d2)
+ && !(d2 < d)
+ && !(d > d2)
+ && (d2 > d);
+}
+
+int main()
+{
+ constexpr D<int> d{42};
+ constexpr D<int> d2{24};
+
+ static_assert (check_eq (d, d));
+ static_assert (check_less (d2, d));
+
+ constexpr E<float> e { 3.14 };
+ constexpr E<float> ee { 2.72 };
+ static_assert (check_eq (e, e));
+ static_assert (check_less (ee, e));
+
+ constexpr F<char> f { 'b' };
+ static_assert (check_eq (f, 'b'));
+ static_assert (check_less (f, 'c'));
+ static_assert (check_less ('a', f));
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth2.C
new file mode 100644
index 0000000..cf23c97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth2.C
@@ -0,0 +1,43 @@
+// Test with only spaceship defaulted.
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+struct D
+{
+ int i;
+ auto operator<=>(const D& x) const = default;
+ // auto operator==(const D& x) const = default;
+ // auto operator!=(const D& x) const = default;
+ // auto operator<(const D& x) const = default;
+ // auto operator<=(const D& x) const = default;
+ // auto operator>(const D& x) const = default;
+ // auto operator>=(const D& x) const = default;
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+int main()
+{
+ D d{42};
+ D d2{24};
+
+ assert (is_eq (d <=> d));
+ assert (is_lteq (d <=> d));
+ assert (is_gteq (d <=> d));
+ assert (is_lt (d2 <=> d));
+ assert (is_lteq (d2 <=> d));
+ assert (is_gt (d <=> d2));
+ assert (is_gteq (d <=> d2));
+
+ assert (d == d);
+ assert (!(d2 == d));
+ assert (!(d == d2));
+ assert (d != d2);
+ assert (!(d2 != d2));
+
+ assert (d2 < d);
+ assert (d2 <= d);
+ assert (d > d2);
+ assert (d >= d2);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3.C
new file mode 100644
index 0000000..0fc5aa2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3.C
@@ -0,0 +1,48 @@
+// Test for reversed candidates.
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+struct D
+{
+ int i;
+ auto operator<=>(int x) const { return i<=>x; }
+ bool operator== (int x) const { return i==x; }
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+int main()
+{
+ D d{42};
+ int d1 = 42;
+ int d2 = 24;
+
+ assert (is_eq (d <=> d1));
+ assert (is_eq (d1 <=> d));
+ assert (is_lteq (d <=> d1));
+ assert (is_lteq (d1 <=> d));
+ assert (is_gteq (d <=> d1));
+ assert (is_gteq (d1 <=> d));
+ assert (is_lt (d2 <=> d));
+ assert (is_lteq (d2 <=> d));
+ assert (is_gt (d <=> d2));
+ assert (is_gteq (d <=> d2));
+
+ assert (d == d1);
+ assert (d1 == d);
+ assert (!(d2 == d));
+ assert (!(d == d2));
+ assert (d != d2);
+ assert (d2 != d);
+ assert (!(d != d1));
+ assert (!(d1 != d));
+
+ assert (d2 < d);
+ assert (d2 <= d);
+ assert (d1 <= d);
+ assert (d > d2);
+ assert (d >= d2);
+ assert (d >= d1);
+ assert (d <= d1);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3a.C
new file mode 100644
index 0000000..89f8489
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth3a.C
@@ -0,0 +1,54 @@
+// Test for reversed candidates.
+// { dg-do run { target c++2a } }
+
+#include <compare>
+
+struct D
+{
+ int i;
+ auto operator<=>(int x) const { return i<=>x; }
+ bool operator== (int x) const { return i==x; }
+};
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while (0)
+
+template <class T>
+void f()
+{
+ D d{42};
+ int d1 = 42;
+ int d2 = 24;
+
+ assert (is_eq (d <=> d1));
+ assert (is_eq (d1 <=> d));
+ assert (is_lteq (d <=> d1));
+ assert (is_lteq (d1 <=> d));
+ assert (is_gteq (d <=> d1));
+ assert (is_gteq (d1 <=> d));
+ assert (is_lt (d2 <=> d));
+ assert (is_lteq (d2 <=> d));
+ assert (is_gt (d <=> d2));
+ assert (is_gteq (d <=> d2));
+
+ assert (d == d1);
+ assert (d1 == d);
+ assert (!(d2 == d));
+ assert (!(d == d2));
+ assert (d != d2);
+ assert (d2 != d);
+ assert (!(d != d1));
+ assert (!(d1 != d));
+
+ assert (d2 < d);
+ assert (d2 <= d);
+ assert (d1 <= d);
+ assert (d > d2);
+ assert (d >= d2);
+ assert (d >= d1);
+ assert (d <= d1);
+}
+
+int main()
+{
+ f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-weak1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-weak1.C
new file mode 100644
index 0000000..1ff3954
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-weak1.C
@@ -0,0 +1,15 @@
+// Test explicit weak_ordering.
+// { dg-do compile { target c++2a } }
+
+#include <compare>
+struct A
+{
+ int i;
+ std::weak_ordering operator<=> (const A&) const = default;
+};
+
+constexpr A a = { 42 };
+constexpr auto c = a <=> a;
+static_assert (std::same_as <decltype (c), const std::weak_ordering>);
+static_assert (std::is_eq (c));
+
diff --git a/gcc/testsuite/g++.dg/lookup/pr21802.C b/gcc/testsuite/g++.dg/lookup/pr21802.C
index 139f7b4..18b2219 100644
--- a/gcc/testsuite/g++.dg/lookup/pr21802.C
+++ b/gcc/testsuite/g++.dg/lookup/pr21802.C
@@ -60,6 +60,7 @@ struct Y : virtual X
template <typename T>
int operator&(T x) { return m + x + 1; }
friend int operator==(Y o, int x) { return o.m + x + 1; }
+ int operator!=(int x) { return m + x + 1; }
};
/* The folloiwng "FooN" functions each contain a different way to call and to
@@ -81,7 +82,6 @@ Foo1 (T)
{ int t = x | I; assert (t == 7); }
{ int t = x && I; assert (t == 7); }
{ int t = x || I; assert (t == 7); }
- { int t = x != I; assert (t == 7); }
{ int t = x < I; assert (t == 7); }
{ int t = x <= I; assert (t == 7); }
{ int t = x > I; assert (t == 7); }
@@ -104,6 +104,7 @@ Foo1 (T)
{ int t = x & I; assert (t == 8); }
{ int t = &x; assert (t == 8); }
{ int t = x == I; assert (t == 8); }
+ { int t = x != I; assert (t == 8); }
}
template <typename T>
@@ -204,7 +205,6 @@ Foo4 (T)
{ int t = x.operator| (I); assert (t == 7); }
{ int t = x.operator&& (I); assert (t == 7); }
{ int t = x.operator|| (I); assert (t == 7); }
- { int t = x.operator!= (I); assert (t == 7); }
{ int t = x.operator< (I); assert (t == 7); }
{ int t = x.operator<= (I); assert (t == 7); }
{ int t = x.operator> (I); assert (t == 7); }
@@ -227,6 +227,7 @@ Foo4 (T)
{ int t = x.operator& (); assert (t == 8); }
{ int t = x.operator& (I); assert (t == 8); }
{ int t = operator== (x, I); assert (t == 8); }
+ { int t = x.operator!= (I); assert (t == 8); }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
index 62dd18d..c0921bb 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
@@ -11,18 +11,17 @@ public:
operator int() const {return 2;}
};
-bool operator==(const MyInt& a, const int& b) // { dg-message "operator==" } candidate
+bool operator==(const MyInt& a, const int& b) // { dg-message "operator==" "" { target c++17_down } }
{
return (int)a == b;
}
-bool operator==(const MyInt& a, const MyInt& b) // { dg-message "operator==" } candidate
+bool operator==(const MyInt& a, const MyInt& b) // { dg-message "operator==" "" { target c++17_down } }
{
return (int)a == (int)b;
}
bool f()
{
- return 3 == MyInt(); // { dg-error "ambiguous" "err" }
- // { dg-message "operator==" "match candidate text" { target *-*-* } .-1 }
+ return 3 == MyInt(); // { dg-error "ambiguous" "err" { target c++17_down } }
}