Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -499,18 +499,9 @@ // ::= $H? // ::= $I? // ::= $J? - // ::= $0A@ MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); - // The null member function pointer is $0A@ in function templates and crashes - // MSVC when used in class templates, so we don't know what they really look - // like. - if (!MD) { - Out << "$0A@"; - return; - } - char Code = '\0'; switch (IM) { case MSInheritanceAttr::Keyword_single_inheritance: Code = '1'; break; @@ -519,28 +510,38 @@ case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'J'; break; } - Out << '$' << Code << '?'; - // If non-virtual, mangle the name. If virtual, mangle as a virtual memptr // thunk. uint64_t NVOffset = 0; uint64_t VBTableOffset = 0; uint64_t VBPtrOffset = 0; - if (MD->isVirtual()) { - MicrosoftVTableContext *VTContext = - cast(getASTContext().getVTableContext()); - const MicrosoftVTableContext::MethodVFTableLocation &ML = - VTContext->getMethodVFTableLocation(GlobalDecl(MD)); - mangleVirtualMemPtrThunk(MD, ML); - NVOffset = ML.VFPtrOffset.getQuantity(); - VBTableOffset = ML.VBTableIndex * 4; - if (ML.VBase) { - const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD); - VBPtrOffset = Layout.getVBPtrOffset().getQuantity(); + if (MD) { + Out << '$' << Code << '?'; + if (MD->isVirtual()) { + MicrosoftVTableContext *VTContext = + cast(getASTContext().getVTableContext()); + const MicrosoftVTableContext::MethodVFTableLocation &ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); + mangleVirtualMemPtrThunk(MD, ML); + NVOffset = ML.VFPtrOffset.getQuantity(); + VBTableOffset = ML.VBTableIndex * 4; + if (ML.VBase) { + const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD); + VBPtrOffset = Layout.getVBPtrOffset().getQuantity(); + } + } else { + mangleName(MD); + mangleFunctionEncoding(MD); } } else { - mangleName(MD); - mangleFunctionEncoding(MD); + // Null single inheritance member functions are encoded as a simple nullptr. + if (IM == MSInheritanceAttr::Keyword_single_inheritance) { + Out << "$0A@"; + return; + } + if (IM == MSInheritanceAttr::Keyword_unspecified_inheritance) + VBTableOffset = -1; + Out << '$' << Code; } if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM)) Index: test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp =================================================================== --- test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp +++ test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp @@ -1,5 +1,24 @@ // RUN: %clang_cc1 -Wno-microsoft -fms-extensions -fno-rtti -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +template +struct J {}; + +struct __single_inheritance M; +J m; +// CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A" + +struct __multiple_inheritance N; +J n; +// CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A" + +struct __virtual_inheritance O; +J o; +// CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A" + +struct P; +J

p; +// CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A" + #pragma pointers_to_members(full_generality, virtual_inheritance) struct S {