From b2fef1a0b0c2193bd9aba957b8050098728c5405 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 29 Aug 2018 04:12:44 +0000 Subject: [PATCH] Add support for various C++14 demanglings. Mostly this includes and return values. Additionally, this fixes a fairly obscure back-referencing bug that was encountered in one of the C++14 tests, which is that if you have something like Foo<&bar, &bar> then the `bar` forms a backreference. llvm-svn: 340896 --- llvm/lib/Demangle/MicrosoftDemangle.cpp | 54 ++++++++++++++++++++-------- llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 5 +-- llvm/lib/Demangle/MicrosoftDemangleNodes.h | 19 +++++----- llvm/test/Demangle/ms-cxx14.test | 37 +++++++++++++++++++ 4 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 llvm/test/Demangle/ms-cxx14.test diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 0eb0c6d..5081f94 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -191,6 +191,8 @@ static bool isTagType(StringView S) { return false; } +static bool isCustomType(StringView S) { return S[0] == '?'; } + static bool isPointerType(StringView S) { if (S.startsWith("$$Q")) // foo && return true; @@ -288,6 +290,7 @@ private: // Parser functions. This is a recursive-descent parser. TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM); PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName); + CustomTypeNode *demangleCustomType(StringView &MangledName); TagTypeNode *demangleClassType(StringView &MangledName); PointerTypeNode *demanglePointerType(StringView &MangledName); PointerTypeNode *demangleMemberPointerType(StringView &MangledName); @@ -304,6 +307,7 @@ private: int64_t demangleSigned(StringView &MangledName); void memorizeString(StringView s); + void memorizeIdentifier(IdentifierNode *Identifier); /// Allocate a copy of \p Borrowed into memory that we own. StringView copyString(StringView Borrowed); @@ -972,6 +976,19 @@ NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { return Backrefs.Names[I]; } +void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { + // 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); + Identifier->output(OS, OF_Default); + OS << '\0'; + char *Name = OS.getBuffer(); + + StringView Owned = copyString(Name); + memorizeString(Owned); + std::free(Name); +} + IdentifierNode * Demangler::demangleTemplateInstantiationName(StringView &MangledName, NameBackrefBehavior NBB) { @@ -990,18 +1007,8 @@ Demangler::demangleTemplateInstantiationName(StringView &MangledName, if (Error) return nullptr; - if (NBB & NBB_Template) { - // 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); - Identifier->output(OS, OF_Default); - OS << '\0'; - char *Name = OS.getBuffer(); - - StringView Owned = copyString(Name); - memorizeString(Owned); - std::free(Name); - } + if (NBB & NBB_Template) + memorizeIdentifier(Identifier); return Identifier; } @@ -1749,6 +1756,8 @@ TypeNode *Demangler::demangleType(StringView &MangledName, MangledName.consumeFront("$$A6"); Ty = demangleFunctionType(MangledName, false); } + } else if (isCustomType(MangledName)) { + Ty = demangleCustomType(MangledName); } else { Ty = demanglePrimitiveType(MangledName); assert(Ty && !Error); @@ -1837,6 +1846,19 @@ Demangler::demangleFunctionEncoding(StringView &MangledName) { return Symbol; } +CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { + assert(MangledName.startsWith('?')); + MangledName.popFront(); + + CustomTypeNode *CTN = Arena.alloc(); + CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true); + if (!MangledName.consumeFront('@')) + Error = true; + if (Error) + return nullptr; + return CTN; +} + // Reads a primitive type. PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { if (MangledName.consumeFront("$$T")) @@ -2131,8 +2153,12 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { // I - virtual inheritance // J - unspecified inheritance char InheritanceSpecifier = MangledName.popFront(); - SymbolNode *S = - MangledName.startsWith('?') ? parse(MangledName) : nullptr; + SymbolNode *S = nullptr; + if (MangledName.startsWith('?')) { + S = parse(MangledName); + memorizeIdentifier(S->Name->getUnqualifiedIdentifier()); + } + switch (InheritanceSpecifier) { case 'J': TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 9610981..9d1aa1a 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -565,9 +565,10 @@ void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { Type->outputPost(OS, Flags); } -void CustomNode::output(OutputStream &OS, OutputFlags Flags) const { - OS << Name; +void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { + Identifier->output(OS, Flags); } +void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const { Components->output(OS, Flags, "::"); diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.h b/llvm/lib/Demangle/MicrosoftDemangleNodes.h index 1797403..93845b5 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.h @@ -148,7 +148,10 @@ enum class CallingConv : uint8_t { enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef }; -enum OutputFlags { OF_Default = 0, OF_NoCallingConvention = 1 }; +enum OutputFlags { + OF_Default = 0, + OF_NoCallingConvention = 1, +}; // Types enum class PrimitiveKind { @@ -392,8 +395,8 @@ struct FunctionSignatureNode : public TypeNode { explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {} FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {} - virtual void outputPre(OutputStream &OS, OutputFlags Flags) const; - virtual void outputPost(OutputStream &OS, OutputFlags Flags) const; + void outputPre(OutputStream &OS, OutputFlags Flags) const override; + void outputPost(OutputStream &OS, OutputFlags Flags) const override; // Valid if this FunctionTypeNode is the Pointee of a PointerType or // MemberPointerType. @@ -566,13 +569,13 @@ struct IntrinsicNode : public TypeNode { void output(OutputStream &OS, OutputFlags Flags) const override {} }; -struct CustomNode : public Node { - CustomNode() : Node(NodeKind::Custom) {} +struct CustomTypeNode : public TypeNode { + CustomTypeNode() : TypeNode(NodeKind::Custom) {} - void output(OutputStream &OS, OutputFlags Flags) const override; + void outputPre(OutputStream &OS, OutputFlags Flags) const override; + void outputPost(OutputStream &OS, OutputFlags Flags) const override; - // The string to print. - StringView Name; + IdentifierNode *Identifier; }; struct NodeArrayNode : public Node { diff --git a/llvm/test/Demangle/ms-cxx14.test b/llvm/test/Demangle/ms-cxx14.test new file mode 100644 index 0000000..a630db8 --- /dev/null +++ b/llvm/test/Demangle/ms-cxx14.test @@ -0,0 +1,37 @@ +; These tests are based on clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp +; RUN: llvm-undname < %s | FileCheck %s + +; CHECK-NOT: Invalid mangled name + +??$x@X@@3HA +; CHECK: int x + +?FunctionWithLocalType@@YA?A?@@XZ +; CHECK: __cdecl FunctionWithLocalType(void) + +?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?@@XZ@A +; CHECK: struct ` __cdecl FunctionWithLocalType(void)'::`2'::LocalType ValueFromFunctionWithLocalType + +??R@@QBE?A?@@XZ +; CHECK: __thiscall ::operator()(void) const + +?ValueFromLambdaWithLocalType@@3ULocalType@?1???R@@QBE?A?@@XZ@A +; CHECK: struct ` __thiscall ::operator()(void) const'::`2'::LocalType ValueFromLambdaWithLocalType + +?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?3@XZ@A +; CHECK: struct ` __thiscall ` __cdecl TemplateFuncionWithLocalLambda(int)'::`1'::::operator()(void) const'::`3'::LocalType ValueFromTemplateFuncionWithLocalLambda + +??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z +; CHECK: __cdecl TemplateFuncionWithLocalLambda(int) + +??R@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?1@XZ +; CHECK: __thiscall ` __cdecl TemplateFuncionWithLocalLambda(int)'::`1'::::operator()(void) const + +??$WithPMD@$GA@A@?0@@3HA +; CHECK: int WithPMD<{0, 0, -1}> + +?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A +; CHECK: struct Foo<&int x, &int x> Zoo + +??$unaligned_x@PFAH@@3PFAHA +; CHECK: int __unaligned *unaligned_x -- 2.7.4