Skip to content

Commit 59cb28d

Browse files
[lldb][swift] Consider ImplicitClosure nodes when demangling async funclets
These should be peeled off just like ExplicitClosures when considering async functions. There is another location where they must be handled, but its test case is encountering another bug in the demangler, so these will be addressed in a separate commit
1 parent 9d9ceb2 commit 59cb28d

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@ static bool IsSwiftAsyncFunctionSymbol(swift::Demangle::NodePointer node) {
8787
if (node->getFirstChild()->getKind() == Node::Kind::Static)
8888
node = node->getFirstChild();
8989

90-
// Get the ExplicitClosure or Function node.
90+
// Get the {Implicit, Explicit} Closure or Function node.
9191
// For nested closures in Swift, the demangle tree is inverted: the
92-
// inner-most closure is the top-most ExplicitClosure node.
92+
// inner-most closure is the top-most closure node.
9393
NodePointer func_node = [&] {
9494
if (NodePointer func = childAtPath(node, Node::Kind::Function))
9595
return func;
96+
if (NodePointer implicit = childAtPath(node, Node::Kind::ImplicitClosure))
97+
return implicit;
9698
return childAtPath(node, Node::Kind::ExplicitClosure);
9799
}();
98100

@@ -206,14 +208,17 @@ SwiftLanguageRuntime::AreFuncletsOfSameAsyncFunction(
206208
}
207209

208210
// If there are closures involved, do the closure-specific comparison.
209-
NodePointer closure1 = childAtPath(node1, Node::Kind::ExplicitClosure);
210-
NodePointer closure2 = childAtPath(node2, Node::Kind::ExplicitClosure);
211-
if (closure1 || closure2) {
212-
if (!closure1 || !closure2)
213-
return FuncletComparisonResult::DifferentAsyncFunctions;
214-
return AreFuncletsOfSameAsyncClosure(closure1, closure2)
215-
? FuncletComparisonResult::SameAsyncFunction
216-
: FuncletComparisonResult::DifferentAsyncFunctions;
211+
for (auto closure_kind :
212+
{Node::Kind::ImplicitClosure, Node::Kind::ExplicitClosure}) {
213+
NodePointer closure1 = childAtPath(node1, closure_kind);
214+
NodePointer closure2 = childAtPath(node2, closure_kind);
215+
if (closure1 || closure2) {
216+
if (!closure1 || !closure2)
217+
return FuncletComparisonResult::DifferentAsyncFunctions;
218+
return AreFuncletsOfSameAsyncClosure(closure1, closure2)
219+
? FuncletComparisonResult::SameAsyncFunction
220+
: FuncletComparisonResult::DifferentAsyncFunctions;
221+
}
217222
}
218223

219224
// Otherwise, find the corresponding function and compare the two.

lldb/test/API/lang/swift/async_breakpoints/TestSwiftAsyncBreakpoints.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ def test(self):
2424
self.assertEquals(breakpoint1.GetNumLocations(), 1)
2525
self.assertEquals(breakpoint2.GetNumLocations(), 1)
2626
self.assertEquals(breakpoint3.GetNumLocations(), 1)
27-
# FIXME: there should be two breakpoints here, but the "entry" funclet of the
28-
# implicit closure is mangled slightly differently. rdar://147035260
29-
self.assertEquals(breakpoint4.GetNumLocations(), 3)
27+
self.assertEquals(breakpoint4.GetNumLocations(), 2)
3028
self.assertEquals(breakpoint5.GetNumLocations(), 1)
3129

3230
location11 = breakpoint1.GetLocationAtIndex(0)

lldb/unittests/Symbol/TestSwiftDemangler.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ TEST(TestSwiftDemangleAsyncNames, BasicAsync) {
9090
// swiftc -g -Onone test.swift -o - -emit-ir -module-name a \
9191
// | grep "define.*sayHello"
9292
// func work() async {}
93+
// func async_int() async -> Int { return 42; }
9394
// func sayHello() async {
9495
// let closure: (Any) async -> () = { _ in
9596
// print("hello")
@@ -112,7 +113,11 @@ TEST(TestSwiftDemangleAsyncNames, BasicAsync) {
112113
//
113114
// await inner_closure2(10)
114115
// print("hello")
116+
// async let x = await async_int();
117+
// print(await x);
115118
// }
119+
// async let x = await async_int();
120+
// print(await x);
116121
// await closure(10)
117122
// }
118123
TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
@@ -145,11 +150,24 @@ TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
145150
"$s1a18myNonAsyncFunctionyyFyyYacfU_SiypYacfU_SSypYacfU0_TQ1_",
146151
"$s1a18myNonAsyncFunctionyyFyyYacfU_SiypYacfU_SSypYacfU0_TY2_"};
147152

153+
SmallVector<StringRef> implicit_closure_inside_function = {
154+
"$s1a8sayHelloyyYaFSiyYaYbcfu_",
155+
"$s1a8sayHelloyyYaFSiyYaYbcfu_TQ0_",
156+
"$s1a8sayHelloyyYaFSiyYaYbcfu_TY1_",
157+
};
158+
SmallVector<StringRef> implicit_closure_inside_explicit_closure = {
159+
"$s1a8sayHelloyyYaFyypYacfU_SiyYaYbcfu_",
160+
"$s1a8sayHelloyyYaFyypYacfU_SiyYaYbcfu_TQ0_",
161+
"$s1a8sayHelloyyYaFyypYacfU_SiyYaYbcfu_TY1_",
162+
};
163+
148164
SmallVector<ArrayRef<StringRef>, 0> funclet_groups = {
149165
nested1_funclets,
150166
nested2_funclets1,
151167
nested2_funclets2,
152168
nested2_funclets_top_not_async,
169+
implicit_closure_inside_function,
170+
implicit_closure_inside_explicit_closure,
153171
};
154172

155173
for (ArrayRef<StringRef> funclet_group : funclet_groups)

0 commit comments

Comments
 (0)