diff options
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangle.cpp | 75 | ||||
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangleNodes.h | 3 | ||||
-rw-r--r-- | llvm/test/Demangle/ms-back-references.test | 3 | ||||
-rw-r--r-- | llvm/test/Demangle/ms-operators.test | 6 | ||||
-rw-r--r-- | llvm/test/Demangle/ms-string-literals.test | 11 |
6 files changed, 82 insertions, 28 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 5081f94f387..ad6990c4e21 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -350,8 +350,8 @@ private: VariableSymbolNode * demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, StringView &MangledName); - FunctionSymbolNode *demangleDynamicStructorFunction(StringView &MangledName, - bool IsDestructor); + FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName, + bool IsDestructor); NamedIdentifierNode *demangleSimpleName(StringView &MangledName, bool Memorize); @@ -520,16 +520,35 @@ Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, return VSN; } -FunctionSymbolNode * -Demangler::demangleDynamicStructorFunction(StringView &MangledName, - bool IsDestructor) { +FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, + bool IsDestructor) { DynamicStructorIdentifierNode *DSIN = Arena.alloc<DynamicStructorIdentifierNode>(); DSIN->IsDestructor = IsDestructor; - DSIN->Name = demangleFullyQualifiedTypeName(MangledName); - QualifiedNameNode *QNN = synthesizeQualifiedName(Arena, DSIN); - FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName); - FSN->Name = QNN; + + // What follows is a main symbol name. This may include namespaces or class + // back references. + QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); + + SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); + FunctionSymbolNode *FSN = nullptr; + Symbol->Name = QN; + + if (Symbol->kind() == NodeKind::VariableSymbol) { + DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol); + if (!MangledName.consumeFront('@')) { + Error = true; + return nullptr; + } + + FSN = demangleFunctionEncoding(MangledName); + FSN->Name = synthesizeQualifiedName(Arena, DSIN); + } else { + FSN = static_cast<FunctionSymbolNode *>(Symbol); + DSIN->Name = Symbol->Name; + FSN->Name = synthesizeQualifiedName(Arena, DSIN); + } + return FSN; } @@ -569,9 +588,9 @@ SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { case SpecialIntrinsicKind::RttiBaseClassDescriptor: return demangleRttiBaseClassDescriptorNode(Arena, MangledName); case SpecialIntrinsicKind::DynamicInitializer: - return demangleDynamicStructorFunction(MangledName, false); + return demangleInitFiniStub(MangledName, false); case SpecialIntrinsicKind::DynamicAtexitDestructor: - return demangleDynamicStructorFunction(MangledName, true); + return demangleInitFiniStub(MangledName, true); default: break; } @@ -837,6 +856,8 @@ SymbolNode *Demangler::parse(StringView &MangledName) { // What follows is a main symbol name. This may include namespaces or class // back references. QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); + if (Error) + return nullptr; SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); if (Symbol) { @@ -1325,10 +1346,9 @@ Demangler::demangleStringLiteral(StringView &MangledName) { goto StringLiteralError; } } else { - if (StringByteSize > 32) - Result->IsTruncated = true; - - constexpr unsigned MaxStringByteLength = 32; + // The max byte length is actually 32, but some compilers mangled strings + // incorrectly, so we have to assume it can go higher. + constexpr unsigned MaxStringByteLength = 32 * 4; uint8_t StringBytes[MaxStringByteLength]; unsigned BytesDecoded = 0; @@ -1337,6 +1357,9 @@ Demangler::demangleStringLiteral(StringView &MangledName) { StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); } + if (StringByteSize > BytesDecoded) + Result->IsTruncated = true; + unsigned CharBytes = guessCharByteSize(StringBytes, BytesDecoded, StringByteSize); assert(StringByteSize % CharBytes == 0); @@ -1587,6 +1610,10 @@ FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { return FuncClass(FC_Private | FC_Virtual); case 'F': return FuncClass(FC_Private | FC_Virtual); + case 'G': + return FuncClass(FC_Private | FC_StaticThisAdjust); + case 'H': + return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far); case 'I': return FuncClass(FC_Protected); case 'J': @@ -1760,7 +1787,6 @@ TypeNode *Demangler::demangleType(StringView &MangledName, Ty = demangleCustomType(MangledName); } else { Ty = demanglePrimitiveType(MangledName); - assert(Ty && !Error); if (!Ty || Error) return Ty; } @@ -1976,14 +2002,14 @@ PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); if (MangledName.consumeFront("8")) { - Pointer->ClassParent = demangleFullyQualifiedSymbolName(MangledName); + Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleFunctionType(MangledName, true); } else { Qualifiers PointeeQuals = Q_None; bool IsMember = false; std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName); assert(IsMember); - Pointer->ClassParent = demangleFullyQualifiedSymbolName(MangledName); + Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop); Pointer->Pointee->Quals = PointeeQuals; @@ -2121,18 +2147,21 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { size_t Count = 0; while (!Error && !MangledName.startsWith('@')) { + if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || + MangledName.consumeFront("$$$V")) { + // Empty parameter pack. + continue; + } + ++Count; + // Template parameter lists don't participate in back-referencing. *Current = Arena.alloc<NodeList>(); NodeList &TP = **Current; TemplateParameterReferenceNode *TPRN = nullptr; - if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || - MangledName.consumeFront("$$$V")) { - // Empty parameter pack. - TP.N = nullptr; - } else if (MangledName.consumeFront("$$Y")) { + if (MangledName.consumeFront("$$Y")) { // Template alias TP.N = demangleFullyQualifiedTypeName(MangledName); } else if (MangledName.consumeFront("$$B")) { diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 9d1aa1ac28d..93719f89342 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -223,9 +223,15 @@ void DynamicStructorIdentifierNode::output(OutputStream &OS, else OS << "`dynamic initializer for "; - OS << "'"; - Name->output(OS, Flags); - OS << "''"; + if (Variable) { + OS << "`"; + Variable->output(OS, Flags); + OS << "''"; + } else { + OS << "'"; + Name->output(OS, Flags); + OS << "''"; + } } void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.h b/llvm/lib/Demangle/MicrosoftDemangleNodes.h index 93845b5200b..caa7eb3b526 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.h @@ -322,7 +322,7 @@ enum class NodeKind { LocalStaticGuardVariable, FunctionSymbol, VariableSymbol, - SpecialTableSymbol, + SpecialTableSymbol }; struct Node { @@ -443,6 +443,7 @@ struct DynamicStructorIdentifierNode : public IdentifierNode { void output(OutputStream &OS, OutputFlags Flags) const override; + VariableSymbolNode *Variable = nullptr; QualifiedNameNode *Name = nullptr; bool IsDestructor = false; }; diff --git a/llvm/test/Demangle/ms-back-references.test b/llvm/test/Demangle/ms-back-references.test index 53bc8b449ed..e04fd846721 100644 --- a/llvm/test/Demangle/ms-back-references.test +++ b/llvm/test/Demangle/ms-back-references.test @@ -169,3 +169,6 @@ ?AddEmitPasses@EmitAssemblyHelper@?A0x43583946@@AEAA_NAEAVPassManager@legacy@llvm@@W4BackendAction@clang@@AEAVraw_pwrite_stream@5@PEAV85@@Z ; CHECK: bool __cdecl `anonymous namespace'::EmitAssemblyHelper::AddEmitPasses(class llvm::legacy::PassManager &, enum clang::BackendAction, class llvm::raw_pwrite_stream &, class llvm::raw_pwrite_stream *) + +??$forward@P8?$DecoderStream@$01@media@@AEXXZ@std@@YA$$QAP8?$DecoderStream@$01@media@@AEXXZAAP812@AEXXZ@Z +; CHECK: void (__thiscall media::DecoderStream<2>::*&& __cdecl std::forward<void (__thiscall media::DecoderStream<2>::*)(void)>(void (__thiscall media::DecoderStream<2>::*&)(void)))(void)
\ No newline at end of file diff --git a/llvm/test/Demangle/ms-operators.test b/llvm/test/Demangle/ms-operators.test index d03d9da7eb0..ad3d87807b4 100644 --- a/llvm/test/Demangle/ms-operators.test +++ b/llvm/test/Demangle/ms-operators.test @@ -161,6 +161,9 @@ ??_EBase@@UEAAPEAXI@Z ; CHECK: virtual void * __cdecl Base::`vector deleting dtor'(unsigned int) +??_EBase@@G3AEPAXI@Z +; CHECK: [thunk]: void * __thiscall Base::`vector deleting dtor'`adjustor{4}'(unsigned int) + ??_F?$SomeTemplate@H@@QAEXXZ ; CHECK: void __thiscall SomeTemplate<int>::`default ctor closure'(void) @@ -224,6 +227,9 @@ ??__FFoo@@YAXXZ ; CHECK: void __cdecl `dynamic atexit destructor for 'Foo''(void) +??__F_decisionToDFA@XPathLexer@@0V?$vector@VDFA@dfa@antlr4@@V?$allocator@VDFA@dfa@antlr4@@@std@@@std@@A@YAXXZ +; CHECK: void __cdecl `dynamic atexit destructor for `static class std::vector<class antlr4::dfa::DFA, class std::allocator<class antlr4::dfa::DFA>> XPathLexer::_decisionToDFA''(void) + ??__K_deg@@YAHO@Z ; CHECK: int __cdecl operator ""_deg(long double) diff --git a/llvm/test/Demangle/ms-string-literals.test b/llvm/test/Demangle/ms-string-literals.test index 77a1882b49d..132637c267d 100644 --- a/llvm/test/Demangle/ms-string-literals.test +++ b/llvm/test/Demangle/ms-string-literals.test @@ -761,4 +761,13 @@ ; CHECK: const char16_t * {u"012345678901234"} ??_C@_0CA@KFPHPCC@0?$AA?$AA?$AA1?$AA?$AA?$AA2?$AA?$AA?$AA3?$AA?$AA?$AA4?$AA?$AA?$AA5?$AA?$AA?$AA6?$AA?$AA?$AA?$AA?$AA?$AA?$AA@ -; CHECK: const char32_t * {U"0123456"}
\ No newline at end of file +; CHECK: const char32_t * {U"0123456"} + +; There are too many bytes encoded in this string literal (it should encode a max of 32 bytes) +; but some buggy compilers will incorrectly generate this, so we need to be able to demangle +; both the correct and incorrect versions. +??_C@_0CG@HJGBPLNO@l?$AAo?$AAo?$AAk?$AAA?$AAh?$AAe?$AAa?$AAd?$AAH?$AAa?$AAr?$AAd?$AAB?$AAr?$AAe?$AAa?$AAk?$AA?$AA?$AA@ +; CHECK: const char16_t * {u"lookAheadHardBreak"} + +??_C@_0CG@HJGBPLNO@l?$AAo?$AAo?$AAk?$AAA?$AAh?$AAe?$AAa?$AAd?$AAH?$AAa?$AAr?$AAd?$AAB?$AAr?$AAe?$AA@ +; CHECK: const char16_t * {u"lookAheadHardBre"...}
\ No newline at end of file |