diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 6145539a819e..754390a1ad03 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -969,7 +969,20 @@ static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) { OS << "~"; LLVM_FALLTHROUGH; case OperatorTy::Ctor: + // Output the class name with template arguments a second time. outputNameComponent(OS, *Previous); + + // Structors don't have a name, so outputting the name here actually is a + // no-op. But for template constructors, it needs to output the template + // argument list. e.g. + // + // template + // struct Foo { + // template + // Foo(U); + // }; + // should demangle as -- for example -- Foo(double); + outputNameComponent(OS, *TheName); break; case OperatorTy::Conversion: OS << "operator"; diff --git a/llvm/test/Demangle/ms-templates.test b/llvm/test/Demangle/ms-templates.test index 09995b36f52c..bddc92ffb504 100644 --- a/llvm/test/Demangle/ms-templates.test +++ b/llvm/test/Demangle/ms-templates.test @@ -196,3 +196,6 @@ ??$f@US@@$1?g@1@QEAAXXZ@@YAXXZ ; CHECK: void __cdecl f(void) + +??$?0N@?$Foo@H@@QEAA@N@Z +; CHECK: __cdecl Foo::Foo(double) \ No newline at end of file