Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -368,9 +368,13 @@ void mangleVariableEncoding(const VarDecl *VD); void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD, StringRef Prefix = "$"); + void mangleMemberDataPointerInClassNTTP(const CXXRecordDecl *, + const ValueDecl *); void mangleMemberFunctionPointer(const CXXRecordDecl *RD, const CXXMethodDecl *MD, StringRef Prefix = "$"); + void mangleMemberFunctionPointerInClassNTTP(const CXXRecordDecl *RD, + const CXXMethodDecl *MD); void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, const MethodVFTableLocation &ML); void mangleNumber(int64_t Number); @@ -711,6 +715,28 @@ mangleNumber(VBTableOffset); } +void MicrosoftCXXNameMangler::mangleMemberDataPointerInClassNTTP( + const CXXRecordDecl *RD, const ValueDecl *VD) { + MSInheritanceModel IM = RD->getMSInheritanceModel(); + // ::= + // ::= N + // ::= 8 @ @ + + if (IM != MSInheritanceModel::Single && IM != MSInheritanceModel::Multiple) + return mangleMemberDataPointer(RD, VD, ""); + + if (!VD) { + Out << 'N'; + return; + } + + Out << '8'; + mangleNestedName(VD); + Out << '@'; + mangleUnqualifiedName(VD); + Out << '@'; +} + void MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, const CXXMethodDecl *MD, @@ -775,6 +801,34 @@ mangleNumber(VBTableOffset); } +void MicrosoftCXXNameMangler::mangleMemberFunctionPointerInClassNTTP( + const CXXRecordDecl *RD, const CXXMethodDecl *MD) { + // ::= + // ::= N + // ::= E? + // ::= E? + + if (!MD) { + if (RD->getMSInheritanceModel() != MSInheritanceModel::Single) + return mangleMemberFunctionPointer(RD, MD, ""); + + Out << 'N'; + return; + } + + Out << "E?"; + if (MD->isVirtual()) { + MicrosoftVTableContext *VTContext = + cast(getASTContext().getVTableContext()); + MethodVFTableLocation ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); + mangleVirtualMemPtrThunk(MD, ML); + } else { + mangleName(MD); + mangleFunctionEncoding(MD, /*ShouldMangle=*/true); + } +} + void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( const CXXMethodDecl *MD, const MethodVFTableLocation &ML) { // Get the vftable offset. @@ -1187,6 +1241,11 @@ // ::= [] void MicrosoftCXXNameMangler::mangleNestedName(GlobalDecl GD) { const NamedDecl *ND = cast(GD.getDecl()); + + if (const auto *ID = dyn_cast(ND)) + for (unsigned I = 1, IE = ID->getChainingSize(); I < IE; ++I) + mangleSourceName(""); + const DeclContext *DC = getEffectiveDeclContext(ND); while (!DC->isTranslationUnit()) { if (isa(ND) || isa(ND)) { @@ -1569,7 +1628,6 @@ // ::= 8 @ // ::= A # float // ::= B # double - // ::= E # reference to D // # pointer to member, by component value // ::= F // ::= G @@ -1614,7 +1672,7 @@ mangleTemplateArgValue(TPO->getType().getUnqualifiedType(), TPO->getValue()); } else { - mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); + mangle(ND, "$1?"); } break; } @@ -1743,7 +1801,7 @@ // FIXME: This can only happen as an extension. Invent a mangling. break; } else if (auto *VD = Base.dyn_cast()) { - Out << (T->isReferenceType() ? "E" : "1"); + Out << "E"; mangle(VD); } else { break; @@ -1793,20 +1851,14 @@ if (WithScalarType) mangleType(T, SourceRange(), QMM_Escape); - // FIXME: The below manglings don't include a conversion, so bail if there - // would be one. MSVC mangles the (possibly converted) value of the - // pointer-to-member object as if it were a struct, leading to collisions - // in some cases. - if (!V.getMemberPointerPath().empty()) - break; - const CXXRecordDecl *RD = T->castAs()->getMostRecentCXXRecordDecl(); const ValueDecl *D = V.getMemberPointerDecl(); if (T->isMemberDataPointerType()) - mangleMemberDataPointer(RD, D, ""); + mangleMemberDataPointerInClassNTTP(RD, D); else - mangleMemberFunctionPointer(RD, cast_or_null(D), ""); + mangleMemberFunctionPointerInClassNTTP(RD, + cast_or_null(D)); return; } Index: clang/test/CodeGenCXX/mangle-class-nttp.cpp =================================================================== --- clang/test/CodeGenCXX/mangle-class-nttp.cpp +++ clang/test/CodeGenCXX/mangle-class-nttp.cpp @@ -15,7 +15,7 @@ int n = 0; // CHECK: define weak_odr void @_Z1fIXtl1BadL_Z1nEEEEvv( -// MSABI: define {{.*}} @"??$f@$2UB@@PEBH1?n@@3HAH0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UB@@PEBHE?n@@3HAH0A@@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl1BLPKi0ELi1EEEEvv( // MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A@H00@@@YAXXZ" @@ -86,33 +86,85 @@ struct D { const int Derived::*p; int k; }; template void f() {} // CHECK: define weak_odr void @_Z1fIXtl1DLM7DerivedKi0ELi1EEEEvv -// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0?0H00@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH00@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl1DEEEvv -// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0?0H0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH0A@@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl1DadL_ZN7Derived1zEEEEEvv -// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H0BA@H0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H82@z@@H0A@@@@YAXXZ" template void f(); -#ifndef _WIN32 // CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN1A1aEEEEEEvv -// MSABI-FIXME: define {{.*}} @"??$f@$2UD@@PERDerived@@H0A@H0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8A@@a@@H0A@@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN1A1bEEEEEEvv -// MSABI-FIXME: define {{.*}} @"??$f@$2UD@@PERDerived@@H03H0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8A@@b@@H0A@@@@YAXXZ" template void f(); // FIXME: Is the Ut_1 mangling here correct? // CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN6NestedUt_1kEE8ELi2EEEEvv -// FIXME: This mangles the same as &A::a (bug in the MS ABI). -// MSABI-FIXME: define {{.*}} @"??$f@$2UD@@PERDerived@@H0A@H01@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8@Nested@@k@@H01@@@YAXXZ" template void f(); struct MoreDerived : A, Derived { int z; }; // CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN11MoreDerived1zEEn8EEEEvv -// MSABI-FIXME: define {{.*}} @"??$f@$2UD@@PERDerived@@H0BI@H0A@@@@YAXXZ" +// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8MoreDerived@@z@@H0A@@@@YAXXZ" template void f(); -#endif -// FIXME: Pointers to member functions. +struct DerivedVirtually : virtual A, Nested { int z; }; +struct D2 { const int DerivedVirtually::*p; int k; }; +template void f() {} +// CHECK: define weak_odr void @_Z1fIXtl2D2LM16DerivedVirtuallyKi0ELi1EEEEvv +// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H00@@@YAXXZ" +template void f(); +// CHECK: define weak_odr void @_Z1fIXtl2D2EEEvv +// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H0A@@@@YAXXZ" +template void f(); +// CHECK: define weak_odr void @_Z1fIXtl2D2adL_ZN16DerivedVirtually1zEEEEEvv +// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFBA@A@H0A@@@@YAXXZ" +template void f(); + +// Forward-decl without MS inheritance keyword means unspecified inheritance +// which is different from e. g. single inheritance. +struct UnspecInherStruct; +struct D3 { const int UnspecInherStruct::*p; }; +template void f() {} +struct UnspecInherStruct { int i; }; +// CHECK: define weak_odr void @_Z1fIXtl2D3adL_ZN17UnspecInherStruct1iEEEEEvv +// MSABI: define {{.*}} @"??$f@$2UD3@@PERUnspecInherStruct@@HGA@A@A@@@@YAXXZ" +template void f(); + +// Pointers to member functions. +// Test struct templates instead of function templates so as to cover +// the separate code which handles nullptr in their pointer-to-member arguments. +struct Derived2 : A, Nested { void f(); virtual void g(); }; +struct D4 { void (Derived2::*p)(); }; +template struct S1 { static void fn() {} }; +// CHECK: define weak_odr void @_ZN2S1IXtl2D4adL_ZN8Derived21fEvEEEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ" +template void S1::fn(); +// CHECK: define weak_odr void @_ZN2S1IXtl2D4adL_ZN8Derived21gEvEEEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZE??_92@$BA@AA@@@SAXXZ" +template void S1::fn(); +// CHECK: define weak_odr void @_ZN2S1IXtl2D4EEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZHA@@@@SAXXZ" +template void S1::fn(); + +struct NoInheritance { void f(); }; +struct D5 { void (NoInheritance::*p)(); }; +template struct S2 { static void fn() {} }; +// CHECK: define weak_odr void @_ZN2S2IXtl2D5adL_ZN13NoInheritance1fEvEEEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S2@$2UD5@@P8NoInheritance@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ" +template void S2::fn(); +// CHECK: define weak_odr void @_ZN2S2IXtl2D5EEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S2@$2UD5@@P8NoInheritance@@EAAXXZN@@@SAXXZ" +template void S2::fn(); + +struct NoInheritanceButUnspecified; +struct D6 { void (NoInheritanceButUnspecified::*p)(); }; +template struct S3 { static void fn() {} }; +// CHECK: define weak_odr void @_ZN2S3IXtl2D6EEE2fnEv +// MSABI: define {{.*}} @"?fn@?$S3@$2UD6@@P8NoInheritanceButUnspecified@@EAAXXZJA@A@?0@@@SAXXZ" +template void S3::fn(); + union E { int n; @@ -204,8 +256,6 @@ template void f(); // Empty and nearly-empty unions. -// Some of the MSVC manglings here are our invention, because MSVC rejects, but -// seem likely to be right. union H1 {}; union H2 { int : 1, : 2, : 3; }; union H3 { int : 1, a, : 2, b, : 3; }; Index: clang/test/CodeGenCXX/mangle-ms-templates.cpp =================================================================== --- clang/test/CodeGenCXX/mangle-ms-templates.cpp +++ clang/test/CodeGenCXX/mangle-ms-templates.cpp @@ -272,7 +272,7 @@ }; extern const record inst; void recref(type1) {} -// CHECK: "?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z" +// CHECK: "?recref@@YAXU?$type1@$1?inst@@3Urecord@@B@@@Z" struct _GUID {}; struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid; @@ -286,7 +286,7 @@ void fun(UUIDType1 a) {} // CHECK: "?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z" void fun(UUIDType2 b) {} -// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z" +// CHECK: "?fun@@YAXU?$UUIDType2@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z" template struct TypeWithFriendDefinition { friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition) {}