diff options
-rw-r--r-- | libcxxabi/src/cxa_demangle.cpp | 101 | ||||
-rw-r--r-- | libcxxabi/test/test_demangle.pass.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Demangle/ItaniumDemangle.cpp | 102 |
3 files changed, 116 insertions, 91 deletions
diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index 9a2c83a9bec..08a2b2bf646 100644 --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -25,11 +25,10 @@ #include <cstdlib> #include <cstring> #include <numeric> +#include <utility> #include <vector> - namespace { - enum : int { demangle_unknown_error = -4, demangle_invalid_args = -3, @@ -55,8 +54,7 @@ public: KEnableIfAttr, KObjCProtoName, KPointerType, - KLValueReferenceType, - KRValueReferenceType, + KReferenceType, KPointerToMemberType, KArrayType, KFunctionType, @@ -137,6 +135,12 @@ public: virtual bool hasArraySlow(OutputStream &) const { return false; } virtual bool hasFunctionSlow(OutputStream &) const { return false; } + // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to + // get at a node that actually represents some concrete syntax. + virtual const Node *getSyntaxNode(OutputStream &) const { + return this; + } + void print(OutputStream &S) const { printLeft(S); if (RHSComponentCache != Cache::No) @@ -447,60 +451,56 @@ public: } }; -class LValueReferenceType final : public Node { - const Node *Pointee; - -public: - LValueReferenceType(Node *Pointee_) - : Node(KLValueReferenceType, Pointee_->RHSComponentCache), - Pointee(Pointee_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - return Pointee->hasRHSComponent(S); - } - - void printLeft(OutputStream &s) const override { - Pointee->printLeft(s); - if (Pointee->hasArray(s)) - s += " "; - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += "(&"; - else - s += "&"; - } - void printRight(OutputStream &s) const override { - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += ")"; - Pointee->printRight(s); - } +enum class ReferenceKind { + LValue, + RValue, }; -class RValueReferenceType final : public Node { +// Represents either a LValue or an RValue reference type. +class ReferenceType : public Node { const Node *Pointee; + ReferenceKind RK; + + // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The + // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any + // other combination collapses to a lvalue ref. + std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const { + auto SoFar = std::make_pair(RK, Pointee); + for (;;) { + const Node *SN = SoFar.second->getSyntaxNode(S); + if (SN->getKind() != KReferenceType) + break; + auto *RT = static_cast<const ReferenceType *>(SN); + SoFar.second = RT->Pointee; + SoFar.first = std::min(SoFar.first, RT->RK); + } + return SoFar; + } public: - RValueReferenceType(Node *Pointee_) - : Node(KRValueReferenceType, Pointee_->RHSComponentCache), - Pointee(Pointee_) {} + ReferenceType(Node *Pointee_, ReferenceKind RK_) + : Node(KReferenceType, Pointee_->RHSComponentCache), + Pointee(Pointee_), RK(RK_) {} bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } void printLeft(OutputStream &s) const override { - Pointee->printLeft(s); - if (Pointee->hasArray(s)) + std::pair<ReferenceKind, const Node *> Collapsed = collapse(s); + Collapsed.second->printLeft(s); + if (Collapsed.second->hasArray(s)) s += " "; - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += "(&&"; - else - s += "&&"; - } + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) + s += "("; + s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&"); + } void printRight(OutputStream &s) const override { - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) + std::pair<ReferenceKind, const Node *> Collapsed = collapse(s); + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) s += ")"; - Pointee->printRight(s); + Collapsed.second->printRight(s); } }; @@ -919,6 +919,11 @@ public: size_t Idx = S.CurrentPackIndex; return Idx < Data.size() && Data[Idx]->hasFunction(S); } + const Node *getSyntaxNode(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this; + } void printLeft(OutputStream &S) const override { initializePackExpansion(S); @@ -1046,6 +1051,12 @@ struct ForwardTemplateReference : Node { SwapAndRestore<bool> SavePrinting(Printing, true); return Ref->hasFunction(S); } + const Node *getSyntaxNode(OutputStream &S) const override { + if (Printing) + return this; + SwapAndRestore<bool> SavePrinting(Printing, true); + return Ref->getSyntaxNode(S); + } void printLeft(OutputStream &S) const override { if (Printing) @@ -3444,7 +3455,7 @@ Node *Db::parseType() { Node *Ref = parseType(); if (Ref == nullptr) return nullptr; - Result = make<LValueReferenceType>(Ref); + Result = make<ReferenceType>(Ref, ReferenceKind::LValue); break; } // ::= O <type> # r-value reference (C++11) @@ -3453,7 +3464,7 @@ Node *Db::parseType() { Node *Ref = parseType(); if (Ref == nullptr) return nullptr; - Result = make<RValueReferenceType>(Ref); + Result = make<ReferenceType>(Ref, ReferenceKind::RValue); break; } // ::= C <type> # complex pair (C99) diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index ea7a0faa6af..305e179f90c 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -29749,6 +29749,10 @@ const char* cases[][2] = {"_Z5foldlIJLi1ELi2ELi3EEEv1AIXflplT_EE", "void foldl<1, 2, 3>(A<(... + (1, 2, 3))>)"}, {"_Z5foldrIJLi1ELi2ELi3EEEv1AIXfrplT_EE", "void foldr<1, 2, 3>(A<((1, 2, 3) + ...)>)"}, {"_ZN7PartialIJLi1ELi2EEE5foldrIJLi3ELi4EEEEv1AIXplLi1EplLi2EfRplT_plLi1EplLi2EfrplT_EE", "void Partial<1, 2>::foldr<3, 4>(A<(1) + ((2) + (((3, 4) + ... + (1) + ((2) + (((3, 4) + ...))))))>)"}, + + // reference collapsing: + {"_Z1fIR1SEiOT_", "int f<S&>(S&)"}, + {"_Z1fIJR1SS0_EEiDpOT_", "int f<S&, S>(S&, S&&)"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); diff --git a/llvm/lib/Demangle/ItaniumDemangle.cpp b/llvm/lib/Demangle/ItaniumDemangle.cpp index 30ad30d8271..5bfd2e6ff87 100644 --- a/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -22,12 +22,10 @@ #include <cstdlib> #include <cstring> #include <numeric> +#include <utility> #include <vector> - namespace { - - // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. class Node { @@ -45,8 +43,7 @@ public: KEnableIfAttr, KObjCProtoName, KPointerType, - KLValueReferenceType, - KRValueReferenceType, + KReferenceType, KPointerToMemberType, KArrayType, KFunctionType, @@ -127,6 +124,12 @@ public: virtual bool hasArraySlow(OutputStream &) const { return false; } virtual bool hasFunctionSlow(OutputStream &) const { return false; } + // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to + // get at a node that actually represents some concrete syntax. + virtual const Node *getSyntaxNode(OutputStream &) const { + return this; + } + void print(OutputStream &S) const { printLeft(S); if (RHSComponentCache != Cache::No) @@ -437,60 +440,56 @@ public: } }; -class LValueReferenceType final : public Node { - const Node *Pointee; - -public: - LValueReferenceType(Node *Pointee_) - : Node(KLValueReferenceType, Pointee_->RHSComponentCache), - Pointee(Pointee_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - return Pointee->hasRHSComponent(S); - } - - void printLeft(OutputStream &s) const override { - Pointee->printLeft(s); - if (Pointee->hasArray(s)) - s += " "; - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += "(&"; - else - s += "&"; - } - void printRight(OutputStream &s) const override { - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += ")"; - Pointee->printRight(s); - } +enum class ReferenceKind { + LValue, + RValue, }; -class RValueReferenceType final : public Node { +// Represents either a LValue or an RValue reference type. +class ReferenceType : public Node { const Node *Pointee; + ReferenceKind RK; + + // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The + // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any + // other combination collapses to a lvalue ref. + std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const { + auto SoFar = std::make_pair(RK, Pointee); + for (;;) { + const Node *SN = SoFar.second->getSyntaxNode(S); + if (SN->getKind() != KReferenceType) + break; + auto *RT = static_cast<const ReferenceType *>(SN); + SoFar.second = RT->Pointee; + SoFar.first = std::min(SoFar.first, RT->RK); + } + return SoFar; + } public: - RValueReferenceType(Node *Pointee_) - : Node(KRValueReferenceType, Pointee_->RHSComponentCache), - Pointee(Pointee_) {} + ReferenceType(Node *Pointee_, ReferenceKind RK_) + : Node(KReferenceType, Pointee_->RHSComponentCache), + Pointee(Pointee_), RK(RK_) {} bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } void printLeft(OutputStream &s) const override { - Pointee->printLeft(s); - if (Pointee->hasArray(s)) + std::pair<ReferenceKind, const Node *> Collapsed = collapse(s); + Collapsed.second->printLeft(s); + if (Collapsed.second->hasArray(s)) s += " "; - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += "(&&"; - else - s += "&&"; - } + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) + s += "("; + s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&"); + } void printRight(OutputStream &s) const override { - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) + std::pair<ReferenceKind, const Node *> Collapsed = collapse(s); + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) s += ")"; - Pointee->printRight(s); + Collapsed.second->printRight(s); } }; @@ -909,6 +908,11 @@ public: size_t Idx = S.CurrentPackIndex; return Idx < Data.size() && Data[Idx]->hasFunction(S); } + const Node *getSyntaxNode(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this; + } void printLeft(OutputStream &S) const override { initializePackExpansion(S); @@ -1036,6 +1040,12 @@ struct ForwardTemplateReference : Node { SwapAndRestore<bool> SavePrinting(Printing, true); return Ref->hasFunction(S); } + const Node *getSyntaxNode(OutputStream &S) const override { + if (Printing) + return this; + SwapAndRestore<bool> SavePrinting(Printing, true); + return Ref->getSyntaxNode(S); + } void printLeft(OutputStream &S) const override { if (Printing) @@ -3434,7 +3444,7 @@ Node *Db::parseType() { Node *Ref = parseType(); if (Ref == nullptr) return nullptr; - Result = make<LValueReferenceType>(Ref); + Result = make<ReferenceType>(Ref, ReferenceKind::LValue); break; } // ::= O <type> # r-value reference (C++11) @@ -3443,7 +3453,7 @@ Node *Db::parseType() { Node *Ref = parseType(); if (Ref == nullptr) return nullptr; - Result = make<RValueReferenceType>(Ref); + Result = make<ReferenceType>(Ref, ReferenceKind::RValue); break; } // ::= C <type> # complex pair (C99) |