<div dir="ltr">Hello Richard,<br><br>This commit broke test on the builder:<br><a href="http://lab.llvm.org:8011/builders/llvm-clang-win-x-armv7l/builds/3169">http://lab.llvm.org:8011/builders/llvm-clang-win-x-armv7l/builds/3169</a><br>. . .<br>Failing Tests (1):<br>    Clang :: CodeGenCXX/virtual-compare.cpp<br>    <br>Please have a look ASAP?<br><br>Thanks<br><br>Galina</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jan 19, 2020 at 6:32 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Richard Smith<br>
Date: 2020-01-19T18:31:36-08:00<br>
New Revision: add2b7e44ada46f30715b5c48823a9e9e317e0c3<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/add2b7e44ada46f30715b5c48823a9e9e317e0c3" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/add2b7e44ada46f30715b5c48823a9e9e317e0c3</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/add2b7e44ada46f30715b5c48823a9e9e317e0c3.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/add2b7e44ada46f30715b5c48823a9e9e317e0c3.diff</a><br>
<br>
LOG: List implicit operator== after implicit destructors in a vtable.<br>
<br>
Summary:<br>
We previously listed first declared members, then implicit operator=,<br>
then implicit operator==, then implicit destructors. Per discussion on<br>
<a href="https://github.com/itanium-cxx-abi/cxx-abi/issues/88" rel="noreferrer" target="_blank">https://github.com/itanium-cxx-abi/cxx-abi/issues/88</a>, put the implicit<br>
equality comparison operators at the very end, after all special member<br>
functions.<br>
<br>
Reviewers: rjmccall<br>
<br>
Subscribers: cfe-commits<br>
<br>
Tags: #clang<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D72897" rel="noreferrer" target="_blank">https://reviews.llvm.org/D72897</a><br>
<br>
Added: <br>
    clang/test/CodeGenCXX/virtual-compare.cpp<br>
<br>
Modified: <br>
    clang/lib/AST/VTableBuilder.cpp<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp<br>
index 2b5b74be5961..0bff976905fc 100644<br>
--- a/clang/lib/AST/VTableBuilder.cpp<br>
+++ b/clang/lib/AST/VTableBuilder.cpp<br>
@@ -1474,11 +1474,11 @@ void ItaniumVTableBuilder::AddMethods(<br>
       llvm_unreachable("Found a duplicate primary base!");<br>
   }<br>
<br>
-  const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;<br>
-<br>
   typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;<br>
   NewVirtualFunctionsTy NewVirtualFunctions;<br>
<br>
+  llvm::SmallVector<const CXXMethodDecl*, 4> NewImplicitVirtualFunctions;<br>
+<br>
   // Now go through all virtual member functions and add them.<br>
   for (const auto *MD : RD->methods()) {<br>
     if (!MD->isVirtual())<br>
@@ -1542,24 +1542,30 @@ void ItaniumVTableBuilder::AddMethods(<br>
       }<br>
     }<br>
<br>
-    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {<br>
-      if (MD->isImplicit()) {<br>
-        // Itanium C++ ABI 2.5.2:<br>
-        //   If a class has an implicitly-defined virtual destructor,<br>
-        //   its entries come after the declared virtual function pointers.<br>
-<br>
-        assert(!ImplicitVirtualDtor &&<br>
-               "Did already see an implicit virtual dtor!");<br>
-        ImplicitVirtualDtor = DD;<br>
-        continue;<br>
-      }<br>
-    }<br>
-<br>
-    NewVirtualFunctions.push_back(MD);<br>
-  }<br>
-<br>
-  if (ImplicitVirtualDtor)<br>
-    NewVirtualFunctions.push_back(ImplicitVirtualDtor);<br>
+    if (MD->isImplicit())<br>
+      NewImplicitVirtualFunctions.push_back(MD);<br>
+    else<br>
+      NewVirtualFunctions.push_back(MD);<br>
+  }<br>
+<br>
+  std::stable_sort(<br>
+      NewImplicitVirtualFunctions.begin(), NewImplicitVirtualFunctions.end(),<br>
+      [](const CXXMethodDecl *A, const CXXMethodDecl *B) {<br>
+        if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator())<br>
+          return A->isCopyAssignmentOperator();<br>
+        if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator())<br>
+          return A->isMoveAssignmentOperator();<br>
+        if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))<br>
+          return isa<CXXDestructorDecl>(A);<br>
+        assert(A->getOverloadedOperator() == OO_EqualEqual &&<br>
+               B->getOverloadedOperator() == OO_EqualEqual &&<br>
+               "unexpected or duplicate implicit virtual function");<br>
+        // We rely on Sema to have declared the operator== members in the<br>
+        // same order as the corresponding operator<=> members.<br>
+        return false;<br>
+      });<br>
+  NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),<br>
+                             NewImplicitVirtualFunctions.end());<br>
<br>
   for (const CXXMethodDecl *MD : NewVirtualFunctions) {<br>
     // Get the final overrider.<br>
<br>
diff  --git a/clang/test/CodeGenCXX/virtual-compare.cpp b/clang/test/CodeGenCXX/virtual-compare.cpp<br>
new file mode 100644<br>
index 000000000000..6ffbe8eb86ae<br>
--- /dev/null<br>
+++ b/clang/test/CodeGenCXX/virtual-compare.cpp<br>
@@ -0,0 +1,53 @@<br>
+// RUN: %clang_cc1 -std=c++2a -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s<br>
+<br>
+#include "Inputs/std-compare.h"<br>
+<br>
+// CHECK: @_ZTV1A =<br>
+struct A;<br>
+struct X {<br>
+  // CHECK-SAME: @_ZN1X1xEv<br>
+  virtual void x();<br>
+  friend auto operator<=>(X, X) = default;<br>
+};<br>
+struct Y {<br>
+  virtual ~Y();<br>
+  virtual A &operator=(const A &);<br>
+  friend auto operator<=>(Y, Y) = default;<br>
+};<br>
+struct A : X, Y {<br>
+  // CHECK-SAME: @_ZN1A1fEv<br>
+  virtual void f();<br>
+  // CHECK-SAME: @_ZNKR1AssERKS_<br>
+  virtual std::strong_ordering operator<=>(const A &) const & = default;<br>
+  // CHECK-SAME: @_ZN1A1gEv<br>
+  virtual void g();<br>
+  // CHECK-SAME: @_ZNKO1AssERKS_<br>
+  virtual std::strong_ordering operator<=>(const A &) const && = default;<br>
+  // CHECK-SAME: @_ZN1A1hEv<br>
+  virtual void h();<br>
+<br>
+  // CHECK-SAME: @_ZN1AaSERKS_<br>
+  // implicit virtual A &operator=(const A&) = default;<br>
+<br>
+  // CHECK-SAME: @_ZN1AD1Ev<br>
+  // CHECK-SAME: @_ZN1AD0Ev<br>
+  // implicit virtual ~A();<br>
+<br>
+  // CHECK-SAME: @_ZNKR1AeqERKS_<br>
+  // implicit virtual A &operator==(const A&) const & = default;<br>
+<br>
+  // CHECK-SAME: @_ZNKO1AeqERKS_<br>
+  // implicit virtual A &operator==(const A&) const && = default;<br>
+};<br>
+<br>
+// For Y:<br>
+// CHECK-SAME: @_ZTI1A<br>
+<br>
+// CHECK-SAME: @_ZThn8_N1AD1Ev<br>
+// CHECK-SAME: @_ZThn8_N1AD0Ev<br>
+// virtual ~Y();<br>
+<br>
+// CHECK-SAME: @_ZThn8_N1AaSERKS_<br>
+// virtual A &operator=(const A &);<br>
+<br>
+void A::f() {}<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>