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,27 @@ 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'; + mangleName(RD); + mangleUnqualifiedName(VD); + Out << '@'; +} + void MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, const CXXMethodDecl *MD, @@ -775,6 +800,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. @@ -1569,7 +1622,6 @@ // ::= 8 @ // ::= A # float // ::= B # double - // ::= E # reference to D // # pointer to member, by component value // ::= F // ::= G @@ -1614,7 +1666,7 @@ mangleTemplateArgValue(TPO->getType().getUnqualifiedType(), TPO->getValue()); } else { - mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); + mangle(ND, "$1?"); } break; } @@ -1743,7 +1795,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; @@ -1804,9 +1856,10 @@ 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,13 +86,13 @@ 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 @@ -112,7 +112,62 @@ 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 +259,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) {}