From 9797513c9dc9bd6cbbe866a8520e6c577ffa1827 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuch12@gmail.com> Date: Tue, 11 Mar 2025 08:57:13 +0000 Subject: [PATCH 1/4] [llvm][ItaniumDemangle] Add function name location tracking --- libcxxabi/src/demangle/ItaniumDemangle.h | 91 ++++++++++++-------- libcxxabi/src/demangle/Utility.h | 10 +++ llvm/include/llvm/Demangle/ItaniumDemangle.h | 91 ++++++++++++-------- llvm/include/llvm/Demangle/Utility.h | 10 +++ 4 files changed, 128 insertions(+), 74 deletions(-) diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index eca9ddad66f92..69932e63669bf 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -283,20 +283,11 @@ class Node { } void print(OutputBuffer &OB) const { - printLeft(OB); + OB.printLeft(*this); if (RHSComponentCache != Cache::No) - printRight(OB); + OB.printRight(*this); } - // Print the "left" side of this Node into OutputBuffer. - virtual void printLeft(OutputBuffer &) const = 0; - - // Print the "right". This distinction is necessary to represent C++ types - // that appear on the RHS of their subtype, such as arrays or functions. - // Since most types don't have such a component, provide a default - // implementation. - virtual void printRight(OutputBuffer &) const {} - // Print an initializer list of this type. Returns true if we printed a custom // representation, false if nothing has been printed and the default // representation should be used. @@ -312,6 +303,24 @@ class Node { #ifndef NDEBUG DEMANGLE_DUMP_METHOD void dump() const; #endif + +private: + friend class OutputBuffer; + + // Print the "left" side of this Node into OutputBuffer. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printLeft instead. + virtual void printLeft(OutputBuffer &) const = 0; + + // Print the "right". This distinction is necessary to represent C++ types + // that appear on the RHS of their subtype, such as arrays or functions. + // Since most types don't have such a component, provide a default + // implementation. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printRight instead. + virtual void printRight(OutputBuffer &) const {} }; class NodeArray { @@ -460,11 +469,11 @@ class QualType final : public Node { } void printLeft(OutputBuffer &OB) const override { - Child->printLeft(OB); + OB.printLeft(*Child); printQuals(OB); } - void printRight(OutputBuffer &OB) const override { Child->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); } }; class ConversionOperatorType final : public Node { @@ -493,7 +502,7 @@ class PostfixQualifiedType final : public Node { template<typename Fn> void match(Fn F) const { F(Ty, Postfix); } void printLeft(OutputBuffer &OB) const override { - Ty->printLeft(OB); + OB.printLeft(*Ty); OB += Postfix; } }; @@ -579,7 +588,7 @@ struct AbiTagAttr : Node { std::string_view getBaseName() const override { return Base->getBaseName(); } void printLeft(OutputBuffer &OB) const override { - Base->printLeft(OB); + OB.printLeft(*Base); OB += "[abi:"; OB += Tag; OB += "]"; @@ -646,7 +655,7 @@ class PointerType final : public Node { // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>. if (Pointee->getKind() != KObjCProtoName || !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) { - Pointee->printLeft(OB); + OB.printLeft(*Pointee); if (Pointee->hasArray(OB)) OB += " "; if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) @@ -665,7 +674,7 @@ class PointerType final : public Node { !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) { if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) OB += ")"; - Pointee->printRight(OB); + OB.printRight(*Pointee); } } }; @@ -731,7 +740,7 @@ class ReferenceType : public Node { std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB); if (!Collapsed.second) return; - Collapsed.second->printLeft(OB); + OB.printLeft(*Collapsed.second); if (Collapsed.second->hasArray(OB)) OB += " "; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) @@ -748,7 +757,7 @@ class ReferenceType : public Node { return; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) OB += ")"; - Collapsed.second->printRight(OB); + OB.printRight(*Collapsed.second); } }; @@ -768,7 +777,7 @@ class PointerToMemberType final : public Node { } void printLeft(OutputBuffer &OB) const override { - MemberType->printLeft(OB); + OB.printLeft(*MemberType); if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += "("; else @@ -780,7 +789,7 @@ class PointerToMemberType final : public Node { void printRight(OutputBuffer &OB) const override { if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += ")"; - MemberType->printRight(OB); + OB.printRight(*MemberType); } }; @@ -800,7 +809,7 @@ class ArrayType final : public Node { bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasArraySlow(OutputBuffer &) const override { return true; } - void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); } + void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); } void printRight(OutputBuffer &OB) const override { if (OB.back() != ']') @@ -809,7 +818,7 @@ class ArrayType final : public Node { if (Dimension) Dimension->print(OB); OB += "]"; - Base->printRight(OB); + OB.printRight(*Base); } bool printInitListAsType(OutputBuffer &OB, @@ -853,7 +862,7 @@ class FunctionType final : public Node { // by printing out the return types's left, then print our parameters, then // finally print right of the return type. void printLeft(OutputBuffer &OB) const override { - Ret->printLeft(OB); + OB.printLeft(*Ret); OB += " "; } @@ -861,7 +870,7 @@ class FunctionType final : public Node { OB.printOpen(); Params.printWithComma(OB); OB.printClose(); - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -966,6 +975,8 @@ class FunctionEncoding final : public Node { FunctionRefQual getRefQual() const { return RefQual; } NodeArray getParams() const { return Params; } const Node *getReturnType() const { return Ret; } + const Node *getAttrs() const { return Attrs; } + const Node *getRequires() const { return Requires; } bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasFunctionSlow(OutputBuffer &) const override { return true; } @@ -974,10 +985,11 @@ class FunctionEncoding final : public Node { void printLeft(OutputBuffer &OB) const override { if (Ret) { - Ret->printLeft(OB); + OB.printLeft(*Ret); if (!Ret->hasRHSComponent(OB)) OB += " "; } + Name->print(OB); } @@ -985,8 +997,9 @@ class FunctionEncoding final : public Node { OB.printOpen(); Params.printWithComma(OB); OB.printClose(); + if (Ret) - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -1326,14 +1339,14 @@ class NonTypeTemplateParamDecl final : public Node { template<typename Fn> void match(Fn F) const { F(Name, Type); } void printLeft(OutputBuffer &OB) const override { - Type->printLeft(OB); + OB.printLeft(*Type); if (!Type->hasRHSComponent(OB)) OB += " "; } void printRight(OutputBuffer &OB) const override { Name->print(OB); - Type->printRight(OB); + OB.printRight(*Type); } }; @@ -1378,11 +1391,11 @@ class TemplateParamPackDecl final : public Node { template<typename Fn> void match(Fn F) const { F(Param); } void printLeft(OutputBuffer &OB) const override { - Param->printLeft(OB); + OB.printLeft(*Param); OB += "..."; } - void printRight(OutputBuffer &OB) const override { Param->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); } }; /// An unexpanded parameter pack (either in the expression or type context). If @@ -1447,13 +1460,13 @@ class ParameterPack final : public Node { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printLeft(OB); + OB.printLeft(*Data[Idx]); } void printRight(OutputBuffer &OB) const override { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printRight(OB); + OB.printRight(*Data[Idx]); } }; @@ -1611,13 +1624,13 @@ struct ForwardTemplateReference : Node { if (Printing) return; ScopedOverride<bool> SavePrinting(Printing, true); - Ref->printLeft(OB); + OB.printLeft(*Ref); } void printRight(OutputBuffer &OB) const override { if (Printing) return; ScopedOverride<bool> SavePrinting(Printing, true); - Ref->printRight(OB); + OB.printRight(*Ref); } }; @@ -1769,7 +1782,7 @@ class DtorName : public Node { void printLeft(OutputBuffer &OB) const override { OB += "~"; - Base->printLeft(OB); + OB.printLeft(*Base); } }; @@ -2049,7 +2062,7 @@ class CastExpr : public Node { { ScopedOverride<unsigned> LT(OB.GtIsGt, 0); OB += "<"; - To->printLeft(OB); + OB.printLeft(*To); OB += ">"; } OB.printOpen(); @@ -6180,6 +6193,10 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> { Alloc>::AbstractManglingParser; }; +inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); } + +inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); } + DEMANGLE_NAMESPACE_END #if defined(__clang__) diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h index f1fad35d60d98..055f02634dabb 100644 --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -27,6 +27,8 @@ DEMANGLE_NAMESPACE_BEGIN +class Node; + // Stream that AST nodes write their string representation into after the AST // has been parsed. class OutputBuffer { @@ -79,10 +81,18 @@ class OutputBuffer { OutputBuffer(const OutputBuffer &) = delete; OutputBuffer &operator=(const OutputBuffer &) = delete; + virtual ~OutputBuffer() {} + operator std::string_view() const { return std::string_view(Buffer, CurrentPosition); } + /// Called by the demangler when printing the demangle tree. By + /// default calls into \c Node::print{Left|Right} but can be overriden + /// by clients to track additional state when printing the demangled name. + virtual void printLeft(const Node &N); + virtual void printRight(const Node &N); + /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index b0363c1a7a786..e5569e75690e1 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -281,20 +281,11 @@ class Node { } void print(OutputBuffer &OB) const { - printLeft(OB); + OB.printLeft(*this); if (RHSComponentCache != Cache::No) - printRight(OB); + OB.printRight(*this); } - // Print the "left" side of this Node into OutputBuffer. - virtual void printLeft(OutputBuffer &) const = 0; - - // Print the "right". This distinction is necessary to represent C++ types - // that appear on the RHS of their subtype, such as arrays or functions. - // Since most types don't have such a component, provide a default - // implementation. - virtual void printRight(OutputBuffer &) const {} - // Print an initializer list of this type. Returns true if we printed a custom // representation, false if nothing has been printed and the default // representation should be used. @@ -310,6 +301,24 @@ class Node { #ifndef NDEBUG DEMANGLE_DUMP_METHOD void dump() const; #endif + +private: + friend class OutputBuffer; + + // Print the "left" side of this Node into OutputBuffer. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printLeft instead. + virtual void printLeft(OutputBuffer &) const = 0; + + // Print the "right". This distinction is necessary to represent C++ types + // that appear on the RHS of their subtype, such as arrays or functions. + // Since most types don't have such a component, provide a default + // implementation. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printRight instead. + virtual void printRight(OutputBuffer &) const {} }; class NodeArray { @@ -458,11 +467,11 @@ class QualType final : public Node { } void printLeft(OutputBuffer &OB) const override { - Child->printLeft(OB); + OB.printLeft(*Child); printQuals(OB); } - void printRight(OutputBuffer &OB) const override { Child->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); } }; class ConversionOperatorType final : public Node { @@ -491,7 +500,7 @@ class PostfixQualifiedType final : public Node { template<typename Fn> void match(Fn F) const { F(Ty, Postfix); } void printLeft(OutputBuffer &OB) const override { - Ty->printLeft(OB); + OB.printLeft(*Ty); OB += Postfix; } }; @@ -577,7 +586,7 @@ struct AbiTagAttr : Node { std::string_view getBaseName() const override { return Base->getBaseName(); } void printLeft(OutputBuffer &OB) const override { - Base->printLeft(OB); + OB.printLeft(*Base); OB += "[abi:"; OB += Tag; OB += "]"; @@ -644,7 +653,7 @@ class PointerType final : public Node { // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>. if (Pointee->getKind() != KObjCProtoName || !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) { - Pointee->printLeft(OB); + OB.printLeft(*Pointee); if (Pointee->hasArray(OB)) OB += " "; if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) @@ -663,7 +672,7 @@ class PointerType final : public Node { !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) { if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) OB += ")"; - Pointee->printRight(OB); + OB.printRight(*Pointee); } } }; @@ -729,7 +738,7 @@ class ReferenceType : public Node { std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB); if (!Collapsed.second) return; - Collapsed.second->printLeft(OB); + OB.printLeft(*Collapsed.second); if (Collapsed.second->hasArray(OB)) OB += " "; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) @@ -746,7 +755,7 @@ class ReferenceType : public Node { return; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) OB += ")"; - Collapsed.second->printRight(OB); + OB.printRight(*Collapsed.second); } }; @@ -766,7 +775,7 @@ class PointerToMemberType final : public Node { } void printLeft(OutputBuffer &OB) const override { - MemberType->printLeft(OB); + OB.printLeft(*MemberType); if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += "("; else @@ -778,7 +787,7 @@ class PointerToMemberType final : public Node { void printRight(OutputBuffer &OB) const override { if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += ")"; - MemberType->printRight(OB); + OB.printRight(*MemberType); } }; @@ -798,7 +807,7 @@ class ArrayType final : public Node { bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasArraySlow(OutputBuffer &) const override { return true; } - void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); } + void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); } void printRight(OutputBuffer &OB) const override { if (OB.back() != ']') @@ -807,7 +816,7 @@ class ArrayType final : public Node { if (Dimension) Dimension->print(OB); OB += "]"; - Base->printRight(OB); + OB.printRight(*Base); } bool printInitListAsType(OutputBuffer &OB, @@ -851,7 +860,7 @@ class FunctionType final : public Node { // by printing out the return types's left, then print our parameters, then // finally print right of the return type. void printLeft(OutputBuffer &OB) const override { - Ret->printLeft(OB); + OB.printLeft(*Ret); OB += " "; } @@ -859,7 +868,7 @@ class FunctionType final : public Node { OB.printOpen(); Params.printWithComma(OB); OB.printClose(); - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -964,6 +973,8 @@ class FunctionEncoding final : public Node { FunctionRefQual getRefQual() const { return RefQual; } NodeArray getParams() const { return Params; } const Node *getReturnType() const { return Ret; } + const Node *getAttrs() const { return Attrs; } + const Node *getRequires() const { return Requires; } bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasFunctionSlow(OutputBuffer &) const override { return true; } @@ -972,10 +983,11 @@ class FunctionEncoding final : public Node { void printLeft(OutputBuffer &OB) const override { if (Ret) { - Ret->printLeft(OB); + OB.printLeft(*Ret); if (!Ret->hasRHSComponent(OB)) OB += " "; } + Name->print(OB); } @@ -983,8 +995,9 @@ class FunctionEncoding final : public Node { OB.printOpen(); Params.printWithComma(OB); OB.printClose(); + if (Ret) - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -1324,14 +1337,14 @@ class NonTypeTemplateParamDecl final : public Node { template<typename Fn> void match(Fn F) const { F(Name, Type); } void printLeft(OutputBuffer &OB) const override { - Type->printLeft(OB); + OB.printLeft(*Type); if (!Type->hasRHSComponent(OB)) OB += " "; } void printRight(OutputBuffer &OB) const override { Name->print(OB); - Type->printRight(OB); + OB.printRight(*Type); } }; @@ -1376,11 +1389,11 @@ class TemplateParamPackDecl final : public Node { template<typename Fn> void match(Fn F) const { F(Param); } void printLeft(OutputBuffer &OB) const override { - Param->printLeft(OB); + OB.printLeft(*Param); OB += "..."; } - void printRight(OutputBuffer &OB) const override { Param->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); } }; /// An unexpanded parameter pack (either in the expression or type context). If @@ -1445,13 +1458,13 @@ class ParameterPack final : public Node { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printLeft(OB); + OB.printLeft(*Data[Idx]); } void printRight(OutputBuffer &OB) const override { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printRight(OB); + OB.printRight(*Data[Idx]); } }; @@ -1609,13 +1622,13 @@ struct ForwardTemplateReference : Node { if (Printing) return; ScopedOverride<bool> SavePrinting(Printing, true); - Ref->printLeft(OB); + OB.printLeft(*Ref); } void printRight(OutputBuffer &OB) const override { if (Printing) return; ScopedOverride<bool> SavePrinting(Printing, true); - Ref->printRight(OB); + OB.printRight(*Ref); } }; @@ -1767,7 +1780,7 @@ class DtorName : public Node { void printLeft(OutputBuffer &OB) const override { OB += "~"; - Base->printLeft(OB); + OB.printLeft(*Base); } }; @@ -2047,7 +2060,7 @@ class CastExpr : public Node { { ScopedOverride<unsigned> LT(OB.GtIsGt, 0); OB += "<"; - To->printLeft(OB); + OB.printLeft(*To); OB += ">"; } OB.printOpen(); @@ -6176,6 +6189,10 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> { Alloc>::AbstractManglingParser; }; +inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); } + +inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); } + DEMANGLE_NAMESPACE_END #if defined(__clang__) diff --git a/llvm/include/llvm/Demangle/Utility.h b/llvm/include/llvm/Demangle/Utility.h index e893cceea2cdc..63cddb3d22a0f 100644 --- a/llvm/include/llvm/Demangle/Utility.h +++ b/llvm/include/llvm/Demangle/Utility.h @@ -27,6 +27,8 @@ DEMANGLE_NAMESPACE_BEGIN +class Node; + // Stream that AST nodes write their string representation into after the AST // has been parsed. class OutputBuffer { @@ -79,10 +81,18 @@ class OutputBuffer { OutputBuffer(const OutputBuffer &) = delete; OutputBuffer &operator=(const OutputBuffer &) = delete; + virtual ~OutputBuffer() {} + operator std::string_view() const { return std::string_view(Buffer, CurrentPosition); } + /// Called by the demangler when printing the demangle tree. By + /// default calls into \c Node::print{Left|Right} but can be overriden + /// by clients to track additional state when printing the demangled name. + virtual void printLeft(const Node &N); + virtual void printRight(const Node &N); + /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); From 55a231d4652b08c71ae7ebaf881712f3d5b0f5ba Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuch12@gmail.com> Date: Wed, 9 Apr 2025 10:27:57 +0100 Subject: [PATCH 2/4] fixup! fix test build failure --- llvm/unittests/Demangle/ItaniumDemangleTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/Demangle/ItaniumDemangleTest.cpp b/llvm/unittests/Demangle/ItaniumDemangleTest.cpp index bc6ccc2e16e65..329f33215817a 100644 --- a/llvm/unittests/Demangle/ItaniumDemangleTest.cpp +++ b/llvm/unittests/Demangle/ItaniumDemangleTest.cpp @@ -98,7 +98,7 @@ TEST(ItaniumDemangle, HalfType) { Node *parseType() { OutputBuffer OB; Node *N = AbstractManglingParser<TestParser, TestAllocator>::parseType(); - N->printLeft(OB); + OB.printLeft(*N); std::string_view Name = N->getBaseName(); if (!Name.empty()) Types.push_back(std::string(Name.begin(), Name.end())); From 8526be4c1ef576d98c916645c6f497bdeb0036a2 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuch12@gmail.com> Date: Tue, 15 Apr 2025 11:15:53 +0200 Subject: [PATCH 3/4] fixup! add hooks for insert/prepend/setCurrentPosition --- libcxxabi/src/demangle/Utility.h | 16 ++++++++- llvm/include/llvm/Demangle/ItaniumDemangle.h | 22 +++++++----- llvm/include/llvm/Demangle/Utility.h | 16 ++++++++- llvm/unittests/Demangle/OutputBufferTest.cpp | 37 ++++++++++++++++++++ 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h index 055f02634dabb..bacd80b4b876b 100644 --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -93,6 +93,12 @@ class OutputBuffer { virtual void printLeft(const Node &N); virtual void printRight(const Node &N); + /// Called when we write to this object anywhere other than the end. + virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {} + + /// Called when we reset the \c CurrentPosition of this object. + virtual void notifyPositionChanged(size_t /*OldPos*/, size_t /*NewPos*/) {} + /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); @@ -131,6 +137,8 @@ class OutputBuffer { OutputBuffer &prepend(std::string_view R) { size_t Size = R.size(); + notifyInsertion(/*Position=*/0, /*Count=*/Size); + grow(Size); std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memcpy(Buffer, &*R.begin(), Size); @@ -171,6 +179,9 @@ class OutputBuffer { DEMANGLE_ASSERT(Pos <= CurrentPosition, ""); if (N == 0) return; + + notifyInsertion(Pos, N); + grow(N); std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); std::memcpy(Buffer + Pos, S, N); @@ -178,7 +189,10 @@ class OutputBuffer { } size_t getCurrentPosition() const { return CurrentPosition; } - void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } + void setCurrentPosition(size_t NewPos) { + notifyPositionChanged(CurrentPosition, NewPos); + CurrentPosition = NewPos; + } char back() const { DEMANGLE_ASSERT(CurrentPosition, ""); diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index e5569e75690e1..b4a4c72021fd1 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -38,8 +38,10 @@ DEMANGLE_NAMESPACE_BEGIN template <class T, size_t N> class PODSmallVector { - static_assert(std::is_trivial<T>::value, - "T is required to be a trivial type"); + static_assert(std::is_trivially_copyable<T>::value, + "T is required to be a trivially copyable type"); + static_assert(std::is_trivially_default_constructible<T>::value, + "T is required to be trivially default constructible"); T *First = nullptr; T *Last = nullptr; T *Cap = nullptr; @@ -5752,14 +5754,16 @@ struct FloatData<double> template <> struct FloatData<long double> { -#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \ - defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \ - defined(__ve__) - static const size_t mangled_size = 32; -#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__) - static const size_t mangled_size = 16; +#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106 + static const size_t mangled_size = 32; +#elif __LDBL_MANT_DIG__ == 53 || defined(_MSC_VER) + // MSVC doesn't define __LDBL_MANT_DIG__, but it has long double equal to + // regular double on all current architectures. + static const size_t mangled_size = 16; +#elif __LDBL_MANT_DIG__ == 64 + static const size_t mangled_size = 20; #else - static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms +#error Unknown size for __LDBL_MANT_DIG__ #endif // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. diff --git a/llvm/include/llvm/Demangle/Utility.h b/llvm/include/llvm/Demangle/Utility.h index 63cddb3d22a0f..b30d05c411f3a 100644 --- a/llvm/include/llvm/Demangle/Utility.h +++ b/llvm/include/llvm/Demangle/Utility.h @@ -93,6 +93,12 @@ class OutputBuffer { virtual void printLeft(const Node &N); virtual void printRight(const Node &N); + /// Called when we write to this object anywhere other than the end. + virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {} + + /// Called when we reset the \c CurrentPosition of this object. + virtual void notifyPositionChanged(size_t /*OldPos*/, size_t /*NewPos*/) {} + /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); @@ -131,6 +137,8 @@ class OutputBuffer { OutputBuffer &prepend(std::string_view R) { size_t Size = R.size(); + notifyInsertion(/*Position=*/0, /*Count=*/Size); + grow(Size); std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memcpy(Buffer, &*R.begin(), Size); @@ -171,6 +179,9 @@ class OutputBuffer { DEMANGLE_ASSERT(Pos <= CurrentPosition, ""); if (N == 0) return; + + notifyInsertion(Pos, N); + grow(N); std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); std::memcpy(Buffer + Pos, S, N); @@ -178,7 +189,10 @@ class OutputBuffer { } size_t getCurrentPosition() const { return CurrentPosition; } - void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } + void setCurrentPosition(size_t NewPos) { + notifyPositionChanged(CurrentPosition, NewPos); + CurrentPosition = NewPos; + } char back() const { DEMANGLE_ASSERT(CurrentPosition, ""); diff --git a/llvm/unittests/Demangle/OutputBufferTest.cpp b/llvm/unittests/Demangle/OutputBufferTest.cpp index 76031e523d781..8782389267ed1 100644 --- a/llvm/unittests/Demangle/OutputBufferTest.cpp +++ b/llvm/unittests/Demangle/OutputBufferTest.cpp @@ -93,3 +93,40 @@ TEST(OutputBufferTest, Extend) { std::free(OB.getBuffer()); } + +TEST(OutputBufferTest, Notifications) { + struct MyOutputBuffer : public OutputBuffer { + size_t Inserted = 0; + size_t LatestPos = 0; + + void notifyPositionChanged(size_t OldPos, size_t NewPos) override { + LatestPos = NewPos; + } + + void notifyInsertion(size_t Position, size_t Count) override { + Inserted += Count; + LatestPos = Position; + } + } OB; + + OB.prepend("n"); + EXPECT_EQ(OB.Inserted, 1U); + EXPECT_EQ(OB.LatestPos, 0U); + + OB.prepend(""); + EXPECT_EQ(OB.Inserted, 1U); + EXPECT_EQ(OB.LatestPos, 0U); + + OB.prepend("abc"); + EXPECT_EQ(OB.Inserted, 4U); + EXPECT_EQ(OB.LatestPos, 0U); + + OB.insert(2, "abc", 3U); + EXPECT_EQ(OB.Inserted, 7U); + EXPECT_EQ(OB.LatestPos, 2U); + + OB.setCurrentPosition(3U); + EXPECT_EQ(OB.LatestPos, 3U); + + std::free(OB.getBuffer()); +} From 94128c98291e924a9c91217cd8cd1514def4f587 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuch12@gmail.com> Date: Thu, 17 Apr 2025 07:43:33 +0200 Subject: [PATCH 4/4] fixup! rename API; move notifyInsertion to after new data was written --- libcxxabi/src/demangle/Utility.h | 14 +++++++------- llvm/include/llvm/Demangle/Utility.h | 14 +++++++------- llvm/unittests/Demangle/OutputBufferTest.cpp | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h index bacd80b4b876b..511983ad40f7a 100644 --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -96,8 +96,8 @@ class OutputBuffer { /// Called when we write to this object anywhere other than the end. virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {} - /// Called when we reset the \c CurrentPosition of this object. - virtual void notifyPositionChanged(size_t /*OldPos*/, size_t /*NewPos*/) {} + /// Called when we make the \c CurrentPosition of this object smaller. + virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {} /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. @@ -137,13 +137,13 @@ class OutputBuffer { OutputBuffer &prepend(std::string_view R) { size_t Size = R.size(); - notifyInsertion(/*Position=*/0, /*Count=*/Size); - grow(Size); std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memcpy(Buffer, &*R.begin(), Size); CurrentPosition += Size; + notifyInsertion(/*Position=*/0, /*Count=*/Size); + return *this; } @@ -180,17 +180,17 @@ class OutputBuffer { if (N == 0) return; - notifyInsertion(Pos, N); - grow(N); std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); std::memcpy(Buffer + Pos, S, N); CurrentPosition += N; + + notifyInsertion(Pos, N); } size_t getCurrentPosition() const { return CurrentPosition; } void setCurrentPosition(size_t NewPos) { - notifyPositionChanged(CurrentPosition, NewPos); + notifyDeletion(CurrentPosition, NewPos); CurrentPosition = NewPos; } diff --git a/llvm/include/llvm/Demangle/Utility.h b/llvm/include/llvm/Demangle/Utility.h index b30d05c411f3a..d59d74511dd4f 100644 --- a/llvm/include/llvm/Demangle/Utility.h +++ b/llvm/include/llvm/Demangle/Utility.h @@ -96,8 +96,8 @@ class OutputBuffer { /// Called when we write to this object anywhere other than the end. virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {} - /// Called when we reset the \c CurrentPosition of this object. - virtual void notifyPositionChanged(size_t /*OldPos*/, size_t /*NewPos*/) {} + /// Called when we make the \c CurrentPosition of this object smaller. + virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {} /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. @@ -137,13 +137,13 @@ class OutputBuffer { OutputBuffer &prepend(std::string_view R) { size_t Size = R.size(); - notifyInsertion(/*Position=*/0, /*Count=*/Size); - grow(Size); std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memcpy(Buffer, &*R.begin(), Size); CurrentPosition += Size; + notifyInsertion(/*Position=*/0, /*Count=*/Size); + return *this; } @@ -180,17 +180,17 @@ class OutputBuffer { if (N == 0) return; - notifyInsertion(Pos, N); - grow(N); std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); std::memcpy(Buffer + Pos, S, N); CurrentPosition += N; + + notifyInsertion(Pos, N); } size_t getCurrentPosition() const { return CurrentPosition; } void setCurrentPosition(size_t NewPos) { - notifyPositionChanged(CurrentPosition, NewPos); + notifyDeletion(CurrentPosition, NewPos); CurrentPosition = NewPos; } diff --git a/llvm/unittests/Demangle/OutputBufferTest.cpp b/llvm/unittests/Demangle/OutputBufferTest.cpp index 8782389267ed1..4a30e66eee48e 100644 --- a/llvm/unittests/Demangle/OutputBufferTest.cpp +++ b/llvm/unittests/Demangle/OutputBufferTest.cpp @@ -99,7 +99,7 @@ TEST(OutputBufferTest, Notifications) { size_t Inserted = 0; size_t LatestPos = 0; - void notifyPositionChanged(size_t OldPos, size_t NewPos) override { + void notifyDeletion(size_t OldPos, size_t NewPos) override { LatestPos = NewPos; }