diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp index d644a24d2acbf..34ca845d25d6d 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp @@ -1600,16 +1600,38 @@ std::string SwiftLanguageRuntime::GetParentNameIfClosure(Function &func) { swift_demangle::GetFirstChildOfKind(closure_node, function_kinds); if (!parent_func_node) return ""; - swift_demangle::ReplaceChildWith(*node, *closure_node, *parent_func_node); - ManglingErrorOr mangled = swift::Demangle::mangleNode(node); + NodeFactory factory; + Node *new_global = factory.createNode(Kind::Global); + if (!new_global) + return ""; + // For a given function-like node, async information is a sibling - not a + // child - of the node in the demangling tree. Bring that over as well. + // Don't bring all children, however, as the closure number of `closure_node` + // is also a child of `closure_node`, i.e., it is not related to + // `parent_func_node`. + // + // node (Global) + // | + // |- closure_node + // |- parent_func_node (any function_kind) + // |- async info for parent_func_node + // |- closure number for closure_node + for (auto *child : *closure_node) + if (child->getKind() == Kind::AsyncAwaitResumePartialFunction || + child->getKind() == Kind::AsyncSuspendResumePartialFunction) + new_global->addChild(child, factory); + new_global->addChild(parent_func_node, factory); + + ManglingErrorOr mangled = + swift::Demangle::mangleNode(new_global); if (!mangled.isSuccess()) return ""; if (parent_func_node->getKind() == Kind::Constructor) if (Module *module = func.CalculateSymbolContextModule().get()) - return HandleCtorAndAllocatorVariants(mangled.result(), *module, *node, - *parent_func_node); + return HandleCtorAndAllocatorVariants(mangled.result(), *module, + *new_global, *parent_func_node); return mangled.result(); } } // namespace lldb_private diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h b/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h index 77e82be757f5e..a8aed0262e703 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h @@ -41,9 +41,10 @@ inline NodePointer GetFirstChildOfKind(NodePointer node, inline void ReplaceChildWith(Node &parent, Node &to_replace, Node &new_child) { for (unsigned idx = 0; idx < parent.getNumChildren(); idx++) { auto *child = parent.getChild(idx); - if (child == &to_replace) + if (child == &to_replace) { parent.replaceChild(idx, &new_child); - return; + return; + } } llvm_unreachable("invalid child passed to replaceChildWith"); } diff --git a/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py b/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py index a18495b6b6516..850ee4f5b76c1 100644 --- a/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py +++ b/lldb/test/API/lang/swift/closures_var_not_captured/TestSwiftClosureVarNotCaptured.py @@ -106,6 +106,18 @@ def test_async_closure(self): ) check_no_enhanced_diagnostic(self, thread.frames[0], "dont_find_me") + @swiftTest + # Async variable inspection on Linux/Windows are still problematic. + @skipIf(oslist=["windows", "linux"]) + def test_task_inside_non_async_func(self): + self.build() + (target, process, thread) = self.get_to_bkpt( + "break_task_inside_non_async_function" + ) + check_not_captured_error( + self, thread.frames[0], "x", "task_inside_non_async_function()" + ) + @swiftTest def test_ctor_class_closure(self): self.build() diff --git a/lldb/test/API/lang/swift/closures_var_not_captured/main.swift b/lldb/test/API/lang/swift/closures_var_not_captured/main.swift index ca7901ee1aaed..6edfd6f59e6cb 100644 --- a/lldb/test/API/lang/swift/closures_var_not_captured/main.swift +++ b/lldb/test/API/lang/swift/closures_var_not_captured/main.swift @@ -212,6 +212,18 @@ enum MY_ENUM { } } +func async_foo() async {} + +func task_inside_non_async_function() -> Task { + var x = 10; + var task = Task { + await async_foo() + print("break_task_inside_non_async_function") + } + + return task +} + func_1(arg: 42) func_2(arg: 42) await func_3(arg: 42) @@ -227,3 +239,4 @@ my_struct.struct_computed_property = 10 my_struct.struct_computed_property_didset = 10 let _ = MY_ENUM(input: [1,2]) MY_ENUM.static_func(input_static: [42]) +await task_inside_non_async_function().getResult()