diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index d782da2103b4c..c81b67ecf4fee 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -24,6 +24,7 @@ #include "llvm/Transforms/Utils/Cloning.h" #include #include +#include using namespace clang; using namespace CodeGen; @@ -1308,44 +1309,34 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, CharUnits ComponentWidth = GetTargetTypeStoreSize(getVTableComponentType()); - typedef std::pair AddressPoint; + struct AddressPoint { + const CXXRecordDecl *Base; + size_t Offset; + std::string TypeName; + bool operator<(const AddressPoint &RHS) const { + int D = TypeName.compare(RHS.TypeName); + return D < 0 || (D == 0 && Offset < RHS.Offset); + } + }; std::vector AddressPoints; - for (auto &&AP : VTLayout.getAddressPoints()) - AddressPoints.push_back(std::make_pair( - AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + - AP.second.AddressPointIndex)); - - // Sort the address points for determinism. - // FIXME: It's more efficient to mangle the types before sorting. - llvm::sort(AddressPoints, [this](const AddressPoint &AP1, - const AddressPoint &AP2) { - if (&AP1 == &AP2) - return false; - - std::string S1; - llvm::raw_string_ostream O1(S1); - getCXXABI().getMangleContext().mangleCanonicalTypeName( - QualType(AP1.first->getTypeForDecl(), 0), O1); - O1.flush(); - - std::string S2; - llvm::raw_string_ostream O2(S2); + for (auto &&AP : VTLayout.getAddressPoints()) { + AddressPoint N{AP.first.getBase(), + VTLayout.getVTableOffset(AP.second.VTableIndex) + + AP.second.AddressPointIndex, + {}}; + llvm::raw_string_ostream Stream(N.TypeName); getCXXABI().getMangleContext().mangleCanonicalTypeName( - QualType(AP2.first->getTypeForDecl(), 0), O2); - O2.flush(); - - if (S1 < S2) - return true; - if (S1 != S2) - return false; + QualType(N.Base->getTypeForDecl(), 0), Stream); + AddressPoints.push_back(std::move(N)); + } - return AP1.second < AP2.second; - }); + // Sort the address points for determinism. + llvm::sort(AddressPoints); ArrayRef Comps = VTLayout.vtable_components(); for (auto AP : AddressPoints) { // Create type metadata for the address point. - AddVTableTypeMetadata(VTable, ComponentWidth * AP.second, AP.first); + AddVTableTypeMetadata(VTable, ComponentWidth * AP.Offset, AP.Base); // The class associated with each address point could also potentially be // used for indirect calls via a member function pointer, so we need to @@ -1357,7 +1348,7 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( Context.getMemberPointerType( Comps[I].getFunctionDecl()->getType(), - Context.getRecordType(AP.first).getTypePtr())); + Context.getRecordType(AP.Base).getTypePtr())); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } }