[c++20] Implement P1185R2 (as modified by P2002R0).

For each defaulted operator<=> in a class that doesn't explicitly
declare any operator==, also inject a matching implicit defaulted
operator==.
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
new file mode 100644
index 0000000..1ab7707
--- /dev/null
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+// This test is for [class.compare.default]p3 as modified and renumbered to p4
+// by P2002R0.
+
+namespace std {
+  struct strong_ordering {
+    int n;
+    constexpr operator int() const { return n; }
+    static const strong_ordering less, equal, greater;
+  };
+  constexpr strong_ordering strong_ordering::less = {-1};
+  constexpr strong_ordering strong_ordering::equal = {0};
+  constexpr strong_ordering strong_ordering::greater = {1};
+}
+
+namespace N {
+  struct A {
+    friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default;
+  };
+
+  constexpr bool (*test_a_not_found)(const A&, const A&) = &operator==; // expected-error {{undeclared}}
+
+  constexpr bool operator==(const A&, const A&);
+  constexpr bool (*test_a)(const A&, const A&) = &operator==;
+  static_assert((*test_a)(A(), A()));
+}
+
+struct B1 {
+  virtual std::strong_ordering operator<=>(const B1&) const = default;
+};
+bool (B1::*test_b)(const B1&) const = &B1::operator==;
+
+struct C1 : B1 {
+  // OK, B1::operator== is virtual.
+  bool operator==(const B1&) const override;
+};
+
+struct B2 {
+  std::strong_ordering operator<=>(const B2&) const = default;
+};
+
+struct C2 : B2 {
+  bool operator==(const B2&) const override; // expected-error {{only virtual member functions}}
+};
+
+struct D {
+  std::strong_ordering operator<=>(const D&) const;
+  virtual std::strong_ordering operator<=>(const struct E&) const = 0;
+};
+struct E : D {
+  // expected-error@+2 {{only virtual member functions}}
+  // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}
+  std::strong_ordering operator<=>(const E&) const override = default;
+};
+
+struct F {
+  [[deprecated("oh no")]] std::strong_ordering operator<=>(const F&) const = default; // expected-note 4{{deprecated}}
+};
+void use_f(F f) {
+  void(f <=> f); // expected-warning {{oh no}}
+  void(f < f); // expected-warning {{oh no}}
+  void(f == f); // expected-warning {{oh no}}
+  void(f != f); // expected-warning {{oh no}}
+}
+
+class G {
+  // expected-note@+2 {{implicitly declared private here}}
+  // expected-note-re@+1 {{{{^}}declared private here}}
+  std::strong_ordering operator<=>(const G&) const = default;
+public:
+};
+void use_g(G g) {
+  void(g <=> g); // expected-error {{private}}
+  void(g == g); // expected-error {{private}}
+}
+
+struct H {
+  bool operator==(const H&) const; // expected-note {{here}}
+  constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
+};
+
+struct I {
+  H h; // expected-note {{used to compare}}
+  // expected-error@+1 {{defaulted definition of three-way comparison operator cannot be declared constexpr because the corresponding implicit 'operator==' invokes a non-constexpr comparison function}}
+  constexpr std::strong_ordering operator<=>(const I&) const = default;
+};
+
+struct J {
+  std::strong_ordering operator<=>(const J&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
+  friend std::strong_ordering operator<=>(const J&, const J&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
+};
+void use_j(J j) {
+  void(j == j); // expected-error {{ambiguous}}
+}
+
+namespace DeleteAfterFirstDecl {
+  bool operator==(const struct Q&, const struct Q&);
+  struct Q {
+    struct X {
+      friend std::strong_ordering operator<=>(const X&, const X&);
+    } x; // expected-note {{no viable comparison}}
+    // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
+    friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
+  };
+}
+
+// Note, substitution here results in the second parameter of 'operator=='
+// referring to the first parameter of 'operator==', not to the first parameter
+// of 'operator<=>'.
+// FIXME: Find a case where this matters (attribute enable_if?).
+struct K {
+  friend std::strong_ordering operator<=>(const K &k, decltype(k)) = default;
+};
+bool test_k = K() == K();
+
+namespace NoInjectionIfOperatorEqualsDeclared {
+  struct A {
+    void operator==(int); // expected-note 2{{not viable}}
+    std::strong_ordering operator<=>(const A&) const = default;
+  };
+  bool test_a = A() == A(); // expected-error {{invalid operands}}
+
+  struct B {
+    friend void operator==(int, struct Q); // expected-note {{not viable}}
+    std::strong_ordering operator<=>(const B&) const = default;
+  };
+  bool test_b = B() == B(); // expected-error {{invalid operands}}
+
+  struct C {
+    void operator==(int); // expected-note 2{{not viable}}
+    friend std::strong_ordering operator<=>(const C&, const C&) = default;
+  };
+  bool test_c = C() == C(); // expected-error {{invalid operands}}
+
+  struct D {
+    void f() {
+      void operator==(const D&, int);
+    }
+    struct X {
+      friend void operator==(const D&, int);
+    };
+    friend std::strong_ordering operator<=>(const D&, const D&) = default;
+  };
+  bool test_d = D() == D();
+}
diff --git a/clang/test/CodeGenCXX/cxx2a-three-way-comparison.cpp b/clang/test/CodeGenCXX/cxx2a-three-way-comparison.cpp
index e3c1535..e6be640 100644
--- a/clang/test/CodeGenCXX/cxx2a-three-way-comparison.cpp
+++ b/clang/test/CodeGenCXX/cxx2a-three-way-comparison.cpp
@@ -1,6 +1,41 @@
-// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s --check-prefix=ITANIUM
-// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple x86_64-pc-win32 2>&1 | FileCheck %s --check-prefix=MSABI
-// RUN: not %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple -DBUILTIN 2>&1 | FileCheck %s --check-prefix=BUILTIN
+// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s --check-prefixes=CHECK,ITANIUM
+// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple x86_64-pc-win32 2>&1 | FileCheck %s --check-prefixes=CHECK,MSABI
+
+namespace std {
+  struct strong_ordering {
+    int n;
+    constexpr operator int() const { return n; }
+    static const strong_ordering less, equal, greater;
+  };
+  constexpr strong_ordering strong_ordering::less = {-1};
+  constexpr strong_ordering strong_ordering::equal = {0};
+  constexpr strong_ordering strong_ordering::greater = {1};
+}
+
+struct Primary {
+  virtual void f();
+  std::strong_ordering operator<=>(const Primary&) const = default;
+};
+struct X {
+  virtual struct Y &operator=(Y&&);
+  virtual struct Y &operator=(const Y&);
+  std::strong_ordering operator<=>(const X&) const = default;
+};
+// The vtable for Y should contain the following entries in order:
+//  - Primary::f
+//  - Y::operator<=>
+//  - Y::operator=(const Y&) (implicit)
+//  - Y::operator=(Y&&) (implicit)
+//  - Y::operator==(const Y&) const (implicit)
+// See:
+//   https://github.com/itanium-cxx-abi/cxx-abi/issues/83 for assignment operator
+//   https://github.com/itanium-cxx-abi/cxx-abi/issues/88 for equality comparison
+// FIXME: What rule does MSVC use?
+struct Y : Primary, X {
+  virtual std::strong_ordering operator<=>(const Y&) const = default;
+};
+Y y;
+// ITANIUM: @_ZTV1Y = {{.*}}constant {{.*}} null, {{.*}} @_ZTI1Y {{.*}} @_ZN7Primary1fEv {{.*}} @_ZNK1YssERKS_ {{.*}} @_ZN1YaSERKS_ {{.*}} @_ZN1YaSEOS_ {{.*}} @_ZNK1YeqERKS_ {{.*}} -{{4|8}} {{.*}} @_ZTI1Y {{.*}} @_ZThn8_N1YaSERKS_
 
 struct A {
   void operator<=>(int);
@@ -26,8 +61,11 @@
   return a <=> a;
 }
 
-#ifdef BUILTIN
-void builtin(int a) {
-  a <=> a; // BUILTIN: cannot compile this scalar expression yet
+// CHECK-LABEL: define {{.*}}builtin_cmp
+void builtin_cmp(int a) {
+  // CHECK: icmp slt
+  // CHECK: select
+  // CHECK: icmp eq
+  // CHECK: select
+  a <=> a;
 }
-#endif