summaryrefslogtreecommitdiff
path: root/libcxxabi
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-07-27 17:27:40 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-07-27 17:27:40 +0000
commit27662c46cf056fab09a7432c7e0a159586e307be (patch)
treea216c7b8a6c270e5f2172ac53f9bde7afa9c5d35 /libcxxabi
parentd76e08247544023118a1ded442f2b1295ed25b0c (diff)
[demangler] Support for reference collapsing
llvm.org/PR38323
Diffstat (limited to 'libcxxabi')
-rw-r--r--libcxxabi/src/cxa_demangle.cpp101
-rw-r--r--libcxxabi/test/test_demangle.pass.cpp4
2 files changed, 60 insertions, 45 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]);