llvm_unreachable("Found a duplicate primary base!");
}
+ const CXXDestructorDecl *ImplicitVirtualDtor = nullptr;
+
typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy;
NewVirtualFunctionsTy NewVirtualFunctions;
- llvm::SmallVector<const CXXMethodDecl*, 4> NewImplicitVirtualFunctions;
-
// Now go through all virtual member functions and add them.
for (const auto *MD : RD->methods()) {
if (!MD->isVirtual())
}
}
- if (MD->isImplicit())
- NewImplicitVirtualFunctions.push_back(MD);
- else
- NewVirtualFunctions.push_back(MD);
- }
-
- std::stable_sort(
- NewImplicitVirtualFunctions.begin(), NewImplicitVirtualFunctions.end(),
- [](const CXXMethodDecl *A, const CXXMethodDecl *B) {
- if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator())
- return A->isCopyAssignmentOperator();
- if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator())
- return A->isMoveAssignmentOperator();
- if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))
- return isa<CXXDestructorDecl>(A);
- assert(A->getOverloadedOperator() == OO_EqualEqual &&
- B->getOverloadedOperator() == OO_EqualEqual &&
- "unexpected or duplicate implicit virtual function");
- // We rely on Sema to have declared the operator== members in the
- // same order as the corresponding operator<=> members.
- return false;
- });
- NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
- NewImplicitVirtualFunctions.end());
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (MD->isImplicit()) {
+ // Itanium C++ ABI 2.5.2:
+ // If a class has an implicitly-defined virtual destructor,
+ // its entries come after the declared virtual function pointers.
+
+ assert(!ImplicitVirtualDtor &&
+ "Did already see an implicit virtual dtor!");
+ ImplicitVirtualDtor = DD;
+ continue;
+ }
+ }
+
+ NewVirtualFunctions.push_back(MD);
+ }
+
+ if (ImplicitVirtualDtor)
+ NewVirtualFunctions.push_back(ImplicitVirtualDtor);
for (const CXXMethodDecl *MD : NewVirtualFunctions) {
// Get the final overrider.
+++ /dev/null
-// RUN: %clang_cc1 -std=c++2a -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
-
-#include "Inputs/std-compare.h"
-
-// CHECK: @_ZTV1A =
-struct A;
-struct X {
- // CHECK-SAME: @_ZN1X1xEv
- virtual void x();
- friend auto operator<=>(X, X) = default;
-};
-struct Y {
- virtual ~Y();
- virtual A &operator=(const A &);
- friend auto operator<=>(Y, Y) = default;
-};
-struct A : X, Y {
- // CHECK-SAME: @_ZN1A1fEv
- virtual void f();
- // CHECK-SAME: @_ZNKR1AssERKS_
- virtual std::strong_ordering operator<=>(const A &) const & = default;
- // CHECK-SAME: @_ZN1A1gEv
- virtual void g();
- // CHECK-SAME: @_ZNKO1AssERKS_
- virtual std::strong_ordering operator<=>(const A &) const && = default;
- // CHECK-SAME: @_ZN1A1hEv
- virtual void h();
-
- // CHECK-SAME: @_ZN1AaSERKS_
- // implicit virtual A &operator=(const A&) = default;
-
- // CHECK-SAME: @_ZN1AD1Ev
- // CHECK-SAME: @_ZN1AD0Ev
- // implicit virtual ~A();
-
- // CHECK-SAME: @_ZNKR1AeqERKS_
- // implicit virtual A &operator==(const A&) const & = default;
-
- // CHECK-SAME: @_ZNKO1AeqERKS_
- // implicit virtual A &operator==(const A&) const && = default;
-};
-
-// For Y:
-// CHECK-SAME: @_ZTI1A
-
-// CHECK-SAME: @_ZThn8_N1AD1Ev
-// CHECK-SAME: @_ZThn8_N1AD0Ev
-// virtual ~Y();
-
-// CHECK-SAME: @_ZThn8_N1AaSERKS_
-// virtual A &operator=(const A &);
-
-void A::f() {}