Skip to content

Commit 0a42612

Browse files
authored
Merge pull request swiftlang#76533 from DmT021/wp/OpaqueReturnTypeParent-stable-id
[Demangler] Stable parent identifier in OpaqueReturnTypeParent
2 parents ecce6ac + df9ecd9 commit 0a42612

File tree

4 files changed

+567
-20
lines changed

4 files changed

+567
-20
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,25 @@ class Node {
243243
}
244244
}
245245

246+
static bool deepEquals(const Node *lhs, const Node *rhs) {
247+
if (lhs == rhs)
248+
return true;
249+
if ((!lhs && rhs) || (lhs && !rhs))
250+
return false;
251+
if (!lhs->isSimilarTo(rhs))
252+
return false;
253+
for (auto li = lhs->begin(), ri = rhs->begin(), le = lhs->end(); li != le;
254+
++li, ++ri) {
255+
if (!deepEquals(*li, *ri))
256+
return false;
257+
}
258+
return true;
259+
}
260+
261+
bool isDeepEqualTo(const Node *other) const {
262+
return deepEquals(this, other);
263+
}
264+
246265
bool hasText() const { return NodePayloadKind == PayloadKind::Text; }
247266
llvm::StringRef getText() const {
248267
assert(hasText());

lib/Demangling/Demangler.cpp

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,34 +1532,53 @@ NodePointer Demangler::demangleExtensionContext() {
15321532

15331533
/// Associate any \c OpaqueReturnType nodes with the declaration whose opaque
15341534
/// return type they refer back to.
1535-
static Node *setParentForOpaqueReturnTypeNodes(Demangler &D,
1536-
Node *parent,
1537-
Node *visitedNode) {
1538-
if (!parent || !visitedNode)
1539-
return nullptr;
1540-
if (visitedNode->getKind() == Node::Kind::OpaqueReturnType) {
1535+
/// Implementation for \c setParentForOpaqueReturnTypeNodes. Don't invoke
1536+
/// directly.
1537+
static void setParentForOpaqueReturnTypeNodesImpl(
1538+
Demangler &D, Node &visitedNode,
1539+
llvm::function_ref<StringRef()> getParentID) {
1540+
if (visitedNode.getKind() == Node::Kind::OpaqueReturnType) {
15411541
// If this node is not already parented, parent it.
1542-
if (visitedNode->hasChildren()
1543-
&& visitedNode->getLastChild()->getKind() == Node::Kind::OpaqueReturnTypeParent) {
1544-
return parent;
1542+
if (visitedNode.hasChildren() && visitedNode.getLastChild()->getKind() ==
1543+
Node::Kind::OpaqueReturnTypeParent) {
1544+
return;
15451545
}
1546-
visitedNode->addChild(D.createNode(Node::Kind::OpaqueReturnTypeParent,
1547-
(Node::IndexType)parent), D);
1548-
return parent;
1546+
visitedNode.addChild(D.createNode(Node::Kind::OpaqueReturnTypeParent,
1547+
StringRef(getParentID())),
1548+
D);
1549+
return;
15491550
}
1550-
1551+
15511552
// If this node is one that may in turn define its own opaque return type,
15521553
// stop recursion, since any opaque return type nodes underneath would refer
15531554
// to the nested declaration rather than the one we're looking at.
1554-
if (visitedNode->getKind() == Node::Kind::Function
1555-
|| visitedNode->getKind() == Node::Kind::Variable
1556-
|| visitedNode->getKind() == Node::Kind::Subscript) {
1557-
return parent;
1555+
if (visitedNode.getKind() == Node::Kind::Function ||
1556+
visitedNode.getKind() == Node::Kind::Variable ||
1557+
visitedNode.getKind() == Node::Kind::Subscript) {
1558+
return;
15581559
}
1559-
1560-
for (size_t i = 0, e = visitedNode->getNumChildren(); i < e; ++i) {
1561-
setParentForOpaqueReturnTypeNodes(D, parent, visitedNode->getChild(i));
1560+
1561+
for (Node *child : visitedNode) {
1562+
assert(child);
1563+
setParentForOpaqueReturnTypeNodesImpl(D, *child, getParentID);
15621564
}
1565+
}
1566+
1567+
/// Associate any \c OpaqueReturnType nodes with the declaration whose opaque
1568+
/// return type they refer back to.
1569+
static Node *setParentForOpaqueReturnTypeNodes(Demangler &D, Node *parent,
1570+
Node *visitedNode) {
1571+
if (!parent || !visitedNode)
1572+
return nullptr;
1573+
std::string parentID;
1574+
setParentForOpaqueReturnTypeNodesImpl(D, *visitedNode, [&] {
1575+
if (!parentID.empty())
1576+
return StringRef(parentID);
1577+
const auto mangleResult = mangleNode(parent);
1578+
assert(mangleResult.isSuccess());
1579+
parentID = mangleResult.result();
1580+
return StringRef(parentID);
1581+
});
15631582
return parent;
15641583
}
15651584

unittests/Basic/DemangleTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Demangling/Demangle.h"
14+
#include "swift/Demangling/Demangler.h"
1415
#include "gtest/gtest.h"
1516

1617
using namespace swift::Demangle;
@@ -43,3 +44,17 @@ TEST(Demangle, CustomGenericParameterNames) {
4344
std::string Result = demangleSymbolAsString(SymbolName, Options);
4445
EXPECT_STREQ(DemangledName.c_str(), Result.c_str());
4546
}
47+
48+
TEST(Demangle, DeepEquals) {
49+
static std::string Symbols[]{
50+
#define SYMBOL(Mangled, Demangled) Mangled,
51+
#include "ManglingTestData.def"
52+
};
53+
for (const auto &Symbol : Symbols) {
54+
Demangler D1;
55+
Demangler D2;
56+
auto tree1 = D1.demangleSymbol(Symbol);
57+
auto tree2 = D2.demangleSymbol(Symbol);
58+
EXPECT_TRUE(tree1->isDeepEqualTo(tree2)) << "Failing symbol: " << Symbol;
59+
}
60+
}

0 commit comments

Comments
 (0)