Skip to content

Commit d11fba7

Browse files
Merge pull request #58919 from adrian-prantl/92637892
Add unittests for the remangler, particularly to cover error handling.
2 parents ed17a85 + ef83539 commit d11fba7

File tree

5 files changed

+154
-6
lines changed

5 files changed

+154
-6
lines changed

include/swift/Demangling/Demangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class NodeFactory {
8080
#endif
8181

8282
public:
83+
#ifndef NDEBUG
84+
/// Enabled only by the unit tests to test the failure paths.
85+
bool disableAssertionsForUnitTest = false;
86+
#endif
8387

8488
NodeFactory() {
8589
#ifdef NODE_FACTORY_DEBUGGING

lib/Demangling/DemanglerAssert.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
#include "swift/Demangling/Demangle.h"
2323
#include "swift/Demangling/NamespaceMacros.h"
2424

25-
#if SWIFT_RUNTIME || defined(NDEBUG)
25+
#if defined(NDEBUG) || defined (SWIFT_RUNTIME)
2626

27-
// In the runtime and non-asserts builds, DEMANGLER_ASSERT() returns an error
27+
// In the runtime and non-asserts builds, DEMANGLER_ASSERT() returns an error.
2828
#define DEMANGLER_ASSERT(expr, node) \
2929
do { \
3030
if (!(expr)) \
@@ -33,14 +33,19 @@
3333

3434
#else
3535

36-
// Except in the runtime, assert builds cause DEMANGLER_ASSERT() to assert()
36+
// Except in unittests, assert builds cause DEMANGLER_ASSERT() to assert()
3737
#define DEMANGLER_ASSERT(expr, node) \
3838
do { \
39-
if (!(expr)) \
40-
swift::Demangle::failAssert(__FILE__, __LINE__, node, #expr); \
39+
if (!(expr)) { \
40+
if (Factory.disableAssertionsForUnitTest) \
41+
return ManglingError(ManglingError::AssertionFailed, (node), \
42+
__LINE__); \
43+
else \
44+
swift::Demangle::failAssert(__FILE__, __LINE__, node, #expr); \
45+
} \
4146
} while (0)
4247

43-
#endif // SWIFT_RUNTIME || defined(NDEBUG)
48+
#endif
4449

4550
// DEMANGLER_ALWAYS_ASSERT() *always* fails the program, even in the runtime
4651
#define DEMANGLER_ALWAYS_ASSERT(expr, node) \

unittests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ if(SWIFT_INCLUDE_TOOLS)
1313
add_subdirectory(Localization)
1414
add_subdirectory(IDE)
1515
add_subdirectory(Parse)
16+
add_subdirectory(Remangler)
1617
add_subdirectory(Sema)
1718
add_subdirectory(SIL)
1819
add_subdirectory(SwiftDemangle)
1920
add_subdirectory(Syntax)
21+
2022
if(SWIFT_BUILD_SYNTAXPARSERLIB)
2123
add_subdirectory(SyntaxParser)
2224
endif()

unittests/Remangler/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_swift_unittest(SwiftRemangleTests
2+
RemangleTest.cpp
3+
)
4+
5+
target_link_libraries(SwiftRemangleTests
6+
PRIVATE
7+
swiftBasic
8+
swiftDemangling
9+
LLVMTestingSupport
10+
)

unittests/Remangler/RemangleTest.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/Demangling/Demangle.h"
14+
#include "swift/Demangling/Demangler.h"
15+
#include "swift/Strings.h"
16+
#include "llvm/ADT/StringRef.h"
17+
18+
#include "gtest/gtest.h"
19+
20+
/// Helper class to conveniently construct demangle tree hierarchies.
21+
class NodeBuilder {
22+
using NodePointer = swift::Demangle::NodePointer;
23+
using Kind = swift::Demangle::Node::Kind;
24+
25+
swift::Demangle::Demangler &m_dem;
26+
27+
public:
28+
NodeBuilder(swift::Demangle::Demangler &dem) : m_dem(dem) {
29+
#ifndef NDEBUG
30+
m_dem.disableAssertionsForUnitTest = true;
31+
#endif
32+
}
33+
NodePointer Node(Kind kind, StringRef text) {
34+
return m_dem.createNode(kind, text);
35+
}
36+
NodePointer NodeWithIndex(Kind kind, swift::Demangle::Node::IndexType index) {
37+
return m_dem.createNode(kind, index);
38+
}
39+
NodePointer Node(Kind kind, NodePointer child0 = nullptr,
40+
NodePointer child1 = nullptr,
41+
NodePointer child2 = nullptr,
42+
NodePointer child3 = nullptr) {
43+
NodePointer node = m_dem.createNode(kind);
44+
45+
if (child0)
46+
node->addChild(child0, m_dem);
47+
if (child1)
48+
node->addChild(child1, m_dem);
49+
if (child2)
50+
node->addChild(child2, m_dem);
51+
if (child3)
52+
node->addChild(child3, m_dem);
53+
return node;
54+
}
55+
NodePointer IntType() {
56+
return Node(Node::Kind::Type,
57+
Node(Node::Kind::Structure,
58+
Node(Node::Kind::Module, swift::STDLIB_NAME),
59+
Node(Node::Kind::Identifier, "Int")));
60+
}
61+
NodePointer GlobalTypeMangling(NodePointer type) {
62+
assert(type && type->getKind() == Node::Kind::Type);
63+
return Node(Node::Kind::Global, Node(Node::Kind::TypeMangling, type));
64+
}
65+
NodePointer GlobalType(NodePointer type) {
66+
assert(type && type->getKind() != Node::Kind::Type &&
67+
type->getKind() != Node::Kind::TypeMangling &&
68+
type->getKind() != Node::Kind::Global);
69+
return GlobalTypeMangling(Node(Node::Kind::Type, type));
70+
}
71+
72+
ManglingErrorOr<StringRef> remangle(NodePointer node) {
73+
return mangleNode(
74+
node,
75+
[](SymbolicReferenceKind, const void *) -> NodePointer {
76+
return nullptr;
77+
},
78+
m_dem);
79+
}
80+
std::string remangleResult(NodePointer node) {
81+
return remangle(node).result().str();
82+
}
83+
bool remangleSuccess(NodePointer node) {
84+
return remangle(node).isSuccess();
85+
}
86+
};
87+
88+
TEST(TestSwiftRemangler, DependentGenericConformanceRequirement) {
89+
using namespace swift::Demangle;
90+
using Kind = swift::Demangle::Node::Kind;
91+
Demangler dem;
92+
NodeBuilder b(dem);
93+
{
94+
// Well-formed.
95+
NodePointer n = b.GlobalType(b.Node(
96+
Kind::DependentGenericType,
97+
b.Node(Kind::DependentGenericType,
98+
b.Node(Kind::DependentGenericSignature,
99+
b.NodeWithIndex(Kind::DependentGenericParamCount, 1),
100+
b.Node(Kind::DependentGenericConformanceRequirement,
101+
b.Node(Kind::Type,
102+
b.Node(Kind::DependentGenericParamType,
103+
b.NodeWithIndex(Kind::Index, 0),
104+
b.NodeWithIndex(Kind::Index, 0))),
105+
b.Node(Kind::Type,
106+
b.Node(Kind::Protocol,
107+
b.Node(Kind::Module, "M"),
108+
b.Node(Kind::Identifier, "B"))))),
109+
b.IntType())));
110+
ASSERT_EQ(b.remangleResult(n), "$sSi1M1BRzluuD");
111+
}
112+
{
113+
// Malformed.
114+
NodePointer n = b.GlobalType(b.Node(
115+
Kind::DependentGenericType,
116+
b.Node(Kind::DependentGenericType,
117+
b.Node(Kind::DependentGenericSignature,
118+
b.NodeWithIndex(Kind::DependentGenericParamCount, 1),
119+
b.Node(Kind::DependentGenericConformanceRequirement,
120+
b.Node(Kind::Type,
121+
b.Node(Kind::DependentGenericParamType,
122+
b.NodeWithIndex(Kind::Index, 0),
123+
b.NodeWithIndex(Kind::Index, 0))))),
124+
b.IntType())));
125+
ASSERT_FALSE(b.remangleSuccess(n));
126+
}
127+
}

0 commit comments

Comments
 (0)