Skip to content

Commit 4382c86

Browse files
committed
[lldb] Fix using self in expression evaluation when self is weakly captured
This both fixes printing self when multiple self variables are present (for example, "guard let self = self"), as well as referencing self properties without spelling out self ("self.a" vs "a") when self is captured weakly in closures. rdar://122956043
1 parent 77c0016 commit 4382c86

File tree

4 files changed

+63
-24
lines changed

4 files changed

+63
-24
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -224,26 +224,34 @@ void SwiftUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
224224

225225
LLDB_LOG(log, " [SUE::SC] Compilation unit is swift");
226226

227-
Block *function_block = sym_ctx.GetFunctionBlock();
228-
if (!function_block) {
229-
LLDB_LOG(log, " [SUE::SC] No function block");
227+
Block *innermost_block = sym_ctx.block;
228+
if (!innermost_block) {
229+
LLDB_LOG(log, " [SUE::SC] No block");
230230
return;
231231
}
232232

233-
lldb::VariableListSP variable_list_sp(
234-
function_block->GetBlockVariableList(true));
235-
if (!variable_list_sp) {
236-
LLDB_LOG(log, " [SUE::SC] No block variable list");
233+
VariableList variable_list;
234+
innermost_block->AppendVariables(/*can_create*/
235+
true,
236+
/*get_parent_variables*/ true,
237+
/*stop_if_block_is_inlined_function*/ false,
238+
/*filter*/
239+
[&](Variable *var) {
240+
if (!variable_list.Empty())
241+
return false;
242+
return SwiftLanguageRuntime::IsSelf(*var);
243+
},
244+
&variable_list);
245+
246+
if (variable_list.Empty()) {
247+
LLDB_LOG(log, " [SUE::SC] No self variable");
237248
return;
238249
}
239250

240-
lldb::VariableSP self_var_sp(
241-
variable_list_sp->FindVariable(ConstString("self")));
242-
if (!self_var_sp || !SwiftLanguageRuntime::IsSelf(*self_var_sp)) {
243-
LLDB_LOG(log, " [SUE::SC] No valid `self` variable");
244-
return;
245-
}
251+
assert(variable_list.GetSize() == 1 && variable_list.GetVariableAtIndex(0) &&
252+
"Unexpected variable list state");
246253

254+
lldb::VariableSP self_var_sp = variable_list.GetVariableAtIndex(0);
247255
// If we have a self variable, but it has no location at the current PC, then
248256
// we can't use it. Set the self var back to empty and we'll just pretend we
249257
// are in a regular frame, which is really the best we can do.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,8 @@ bool SwiftLanguageRuntime::IsSelf(Variable &variable) {
15631563
return false;
15641564
node_ptr = node_ptr->getFirstChild();
15651565
return node_ptr->getKind() == swift::Demangle::Node::Kind::Constructor ||
1566-
node_ptr->getKind() == swift::Demangle::Node::Kind::Allocator;
1566+
node_ptr->getKind() == swift::Demangle::Node::Kind::Allocator ||
1567+
node_ptr->getKind() == swift::Demangle::Node::Kind::ExplicitClosure;
15671568
}
15681569

15691570
static swift::Demangle::NodePointer

lldb/test/API/lang/swift/expression/weak_self/TestWeakSelf.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,39 @@
99
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
#
1111
# ------------------------------------------------------------------------------
12-
import lldbsuite.test.lldbinline as lldbinline
13-
from lldbsuite.test.decorators import *
12+
#
13+
import lldb
14+
from lldbsuite.test.lldbtest import *
15+
from lldbsuite.test.decorators import *
16+
import lldbsuite.test.lldbutil as lldbutil
17+
18+
19+
20+
class TestSwiftGenericExtension(TestBase):
21+
@swiftTest
22+
def test(self):
23+
self.build()
24+
25+
target, process, _, _ = lldbutil.run_to_source_breakpoint(
26+
self, "break here for if let success", lldb.SBFileSpec("main.swift")
27+
)
28+
self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker)", "5"])
29+
self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker)", "5"])
30+
self.expect("expr a", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["5"])
31+
32+
breakpoint = target.BreakpointCreateBySourceRegex(
33+
'break here for guard let success', lldb.SBFileSpec('main.swift'), None)
34+
lldbutil.continue_to_breakpoint(process, breakpoint)
35+
self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker)", "5"])
36+
self.expect("expr a", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["5"])
37+
38+
39+
breakpoint = target.BreakpointCreateBySourceRegex(
40+
'break here for if let else', lldb.SBFileSpec('main.swift'), None)
41+
lldbutil.continue_to_breakpoint(process, breakpoint)
42+
self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["nil"])
1443

15-
lldbinline.MakeInlineTest(__file__, globals(), decorators=[swiftTest])
44+
breakpoint = target.BreakpointCreateBySourceRegex(
45+
'break here for guard let else', lldb.SBFileSpec('main.swift'), None)
46+
lldbutil.continue_to_breakpoint(process, breakpoint)
47+
self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["nil"])

lldb/test/API/lang/swift/expression/weak_self/main.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,20 @@ class ClosureMaker {
1919

2020
func getClosure() -> (() -> Int) {
2121
return { [weak self] () -> Int in
22-
if let _self = self {
23-
return _self.a //% self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker?)", "5"])
24-
//% self.expect("expr self!", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker)", "5"])
22+
if let self = self {
23+
return self.a // break here for if let success
2524
} else {
26-
return 0 //% self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["nil"])
25+
return 0 // break here for if let else
2726
}
2827
}
2928
}
3029

3130
func getGuardClosure() -> (() -> Int) {
3231
return { [weak self] () -> Int in
3332
guard let self = self else {
34-
return 0 //% self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["nil"])
33+
return 0 // break here for guard let else
3534
}
36-
return self.a //% self.expect("expr self", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker?)", "5"])
37-
//% self.expect("expr self!", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["ClosureMaker)", "5"])
35+
return self.a // break here for guard let success
3836
}
3937
}
4038
}

0 commit comments

Comments
 (0)