From 4d940e78155164068840bfa72301a7af43665771 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Fri, 27 Jul 2018 17:27:40 +0000 Subject: [PATCH] [demangler] Support for reference collapsing llvm.org/PR38323 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338138 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Demangle/ItaniumDemangle.cpp | 102 +++++++++++++++++-------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/lib/Demangle/ItaniumDemangle.cpp b/lib/Demangle/ItaniumDemangle.cpp index 30ad30d8271..5bfd2e6ff87 100644 --- a/lib/Demangle/ItaniumDemangle.cpp +++ b/lib/Demangle/ItaniumDemangle.cpp @@ -22,12 +22,10 @@ #include #include #include +#include #include - 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 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(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 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 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 SavePrinting(Printing, true); return Ref->hasFunction(S); } + const Node *getSyntaxNode(OutputStream &S) const override { + if (Printing) + return this; + SwapAndRestore 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(Ref); + Result = make(Ref, ReferenceKind::LValue); break; } // ::= O # r-value reference (C++11) @@ -3443,7 +3453,7 @@ Node *Db::parseType() { Node *Ref = parseType(); if (Ref == nullptr) return nullptr; - Result = make(Ref); + Result = make(Ref, ReferenceKind::RValue); break; } // ::= C # complex pair (C99) -- 2.50.1