Index: llvm/lib/Demangle/MicrosoftDemangle.cpp =================================================================== --- llvm/lib/Demangle/MicrosoftDemangle.cpp +++ llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -204,6 +204,13 @@ Far = 1 << 6, }; +enum class SymbolCategory { Function, Variable }; + +enum NameFlags : uint8_t { + NF_TemplateInstantiation = 1 << 2, // This is a template instantiation. + NF_Operator = 1 << 3, // This is an operator +}; + namespace { struct Type; @@ -265,12 +272,10 @@ // Name read from an MangledName string. StringView Str; - // Overloaded operators are represented as special BackReferences in mangled - // symbols. If this is an operator name, "op" has an operator name (e.g. - // ">>"). Otherwise, empty. - StringView Operator; + // Name flags. + NameFlags Flags; - // Template parameters. Null if not a template. + // Template parameters. Only valid if Flags contains NF_TemplateInstantiation. TemplateParams *TParams = nullptr; // Nested BackReferences (e.g. "A::B::C") are represented as a linked list. @@ -541,24 +546,24 @@ for (; TheName->Next; TheName = TheName->Next) { Previous = TheName; OS << TheName->Str; - if (TheName->TParams) + if (TheName->Flags & NF_TemplateInstantiation) outputParameterList(OS, *TheName->TParams); OS << "::"; } // Print out a regular name. - if (TheName->Operator.empty()) { + if (!(TheName->Flags & NF_Operator)) { OS << TheName->Str; - if (TheName->TParams) + if (TheName->Flags & NF_TemplateInstantiation) outputParameterList(OS, *TheName->TParams); return; } // Print out ctor or dtor. - if (TheName->Operator == "dtor") + if (TheName->Str == "dtor") OS << "~"; - if (TheName->Operator == "ctor" || TheName->Operator == "dtor") { + if (TheName->Str == "ctor" || TheName->Str == "dtor") { OS << Previous->Str; if (Previous->TParams) outputParameterList(OS, *Previous->TParams); @@ -566,9 +571,9 @@ } // Print out an overloaded operator. - if (!TheName->Str.empty()) - OS << TheName->Str << "::"; - OS << "operator" << TheName->Operator; + OS << "operator" << TheName->Str; + if (TheName->Flags & NF_TemplateInstantiation) + outputParameterList(OS, *TheName->TParams); } namespace { @@ -853,6 +858,8 @@ } struct Symbol { + SymbolCategory Category; + Name *SymbolName = nullptr; Type *SymbolType = nullptr; }; @@ -906,14 +913,14 @@ Name *demangleFullyQualifiedTypeName(StringView &MangledName); Name *demangleFullyQualifiedSymbolName(StringView &MangledName); - Name *demangleUnqualifiedTypeName(StringView &MangledName); - Name *demangleUnqualifiedSymbolName(StringView &MangledName); + Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize); + Name *demangleUnqualifiedSymbolName(StringView &MangledName, bool Memorize); Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName); Name *demangleNameScopePiece(StringView &MangledName); Name *demangleBackRefName(StringView &MangledName); - Name *demangleClassTemplateName(StringView &MangledName); + Name *demangleTemplateInstantiationName(StringView &MangledName); Name *demangleOperatorName(StringView &MangledName); Name *demangleSimpleName(StringView &MangledName, bool Memorize); Name *demangleAnonymousNamespaceName(StringView &MangledName); @@ -981,9 +988,14 @@ if (Error) return nullptr; // Read a variable. - S->SymbolType = startsWithDigit(MangledName) - ? demangleVariableEncoding(MangledName) - : demangleFunctionEncoding(MangledName); + if (startsWithDigit(MangledName)) { + S->Category = SymbolCategory::Variable; + S->SymbolType = demangleVariableEncoding(MangledName); + } else { + S->Category = SymbolCategory::Function; + S->SymbolType = demangleFunctionEncoding(MangledName); + } + if (Error) return nullptr; @@ -1101,11 +1113,11 @@ return Node; } -Name *Demangler::demangleClassTemplateName(StringView &MangledName) { +Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName) { assert(MangledName.startsWith("?$")); MangledName.consumeFront("?$"); - Name *Node = demangleSimpleName(MangledName, false); + Name *Node = demangleUnqualifiedSymbolName(MangledName, false); if (Error) return nullptr; @@ -1113,6 +1125,8 @@ if (Error) return nullptr; + Node->Flags = NameFlags(Node->Flags | NF_TemplateInstantiation); + // Render this class template name into a string buffer so that we can // memorize it for the purpose of back-referencing. OutputStream OS = OutputStream::create(nullptr, nullptr, 1024); @@ -1250,7 +1264,8 @@ }; Name *Node = Arena.alloc(); - Node->Operator = NameString(); + Node->Str = NameString(); + Node->Flags = NF_Operator; return Node; } @@ -1325,7 +1340,7 @@ // Parses a type name in the form of A@B@C@@ which represents C::B::A. Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { - Name *TypeName = demangleUnqualifiedTypeName(MangledName); + Name *TypeName = demangleUnqualifiedTypeName(MangledName, true); if (Error) return nullptr; assert(TypeName); @@ -1341,7 +1356,7 @@ // Symbol names have slightly different rules regarding what can appear // so we separate out the implementations for flexibility. Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { - Name *SymbolName = demangleUnqualifiedSymbolName(MangledName); + Name *SymbolName = demangleUnqualifiedSymbolName(MangledName, true); if (Error) return nullptr; assert(SymbolName); @@ -1353,7 +1368,8 @@ return QualName; } -Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName) { +Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, + bool Memorize) { // An inner-most name can be a back-reference, because a fully-qualified name // (e.g. Scope + Inner) can contain other fully qualified names inside of // them (for example template parameters), and these nested parameters can @@ -1362,19 +1378,20 @@ return demangleBackRefName(MangledName); if (MangledName.startsWith("?$")) - return demangleClassTemplateName(MangledName); + return demangleTemplateInstantiationName(MangledName); - return demangleSimpleName(MangledName, true); + return demangleSimpleName(MangledName, Memorize); } -Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName) { +Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, + bool Memorize) { if (startsWithDigit(MangledName)) return demangleBackRefName(MangledName); if (MangledName.startsWith("?$")) - return demangleClassTemplateName(MangledName); + return demangleTemplateInstantiationName(MangledName); if (MangledName.startsWith('?')) return demangleOperatorName(MangledName); - return demangleSimpleName(MangledName, true); + return demangleSimpleName(MangledName, Memorize); } Name *Demangler::demangleNameScopePiece(StringView &MangledName) { @@ -1382,7 +1399,7 @@ return demangleBackRefName(MangledName); if (MangledName.startsWith("?$")) - return demangleClassTemplateName(MangledName); + return demangleTemplateInstantiationName(MangledName); if (MangledName.startsWith("?A")) return demangleAnonymousNamespaceName(MangledName); Index: llvm/test/Demangle/ms-back-references.test =================================================================== --- llvm/test/Demangle/ms-back-references.test +++ llvm/test/Demangle/ms-back-references.test @@ -51,3 +51,7 @@ ?foo@0@YAXXZ ; CHECK: void __cdecl foo::foo(void) + +; We have some issues with back-references and class / function templates. +??$?HH@S@@QEAAAEAU0@H@Z +; FIXME: struct S &__cdecl S::operator+(int) \ No newline at end of file Index: llvm/test/Demangle/ms-mangle.test =================================================================== --- llvm/test/Demangle/ms-mangle.test +++ llvm/test/Demangle/ms-mangle.test @@ -64,6 +64,9 @@ ??Hfoo@@QEAAHH@Z ; CHECK: int __cdecl foo::operator+(int) +??$?HH@S@@QEAAAEANH@Z +; CHECK: double & __cdecl S::operator+(int) + ?static_method@foo@@SAPAV1@XZ ; CHECK: static class foo * __cdecl foo::static_method(void)