Skip to content

Commit 49cbc3a

Browse files
Merge pull request #8546 from apple/dl/lldb-Support-breakpoints-on-specific-property-accessor-blocks
[lldb] Support breakpoints on specific property accessor blocks
2 parents 3bcf7f7 + 0f35b80 commit 49cbc3a

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,25 @@ SwiftLanguage::GetMethodNameVariants(ConstString method_name) const {
138138
if (method_name.GetMangledCounterpart(counterpart))
139139
if (SwiftLanguageRuntime::IsSwiftMangledName(counterpart.GetStringRef()))
140140
variant_names.emplace_back(counterpart, eFunctionNameTypeFull);
141+
142+
// Properties can have multiple accessor blocks. This section of code supports
143+
// breakpoints on accessor blocks by name.
144+
//
145+
// By default, the name `A.B` is treated as a fully qualified name, where `B`
146+
// is the basename. However, some names can be interpreted in two ways, for
147+
// example `A.get`. First, it can refer to the name `get` (in module `A`, or
148+
// in type `A`). Second, it can refer the *getter* block for property `A`.
149+
// LLDB's baseline behavior handles the first case. The second case is
150+
// produced here as a variant name.
151+
for (StringRef suffix : {".get", ".set", ".willset", ".didset"})
152+
if (method_name.GetStringRef().ends_with(suffix)) {
153+
// The method name, complete with suffix, *is* the variant.
154+
variant_names.emplace_back(method_name, eFunctionNameTypeFull |
155+
eFunctionNameTypeBase |
156+
eFunctionNameTypeMethod);
157+
break;
158+
}
159+
141160
return variant_names;
142161
}
143162

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
SWIFT_SOURCES := main.swift
3+
4+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
5+
6+
class TestCase(TestBase):
7+
@swiftTest
8+
def test(self):
9+
"""Test that a breakpoint on a property accessor can be set by name."""
10+
self.build()
11+
exe = self.getBuildArtifact("a.out")
12+
target = self.dbg.CreateTarget(exe)
13+
for name in (
14+
"read_only.get",
15+
"read_write.get",
16+
"read_write.set",
17+
"observed.willset",
18+
"observed.didset",
19+
):
20+
bp = target.BreakpointCreateByName(name, "a.out")
21+
self.assertEqual(bp.num_locations, 1, f"{name} breakpoint failed")
22+
23+
# Setting a breakpoint on the name "get" should not create a breakpoint
24+
# matching property getters. The other accerssor suffixes should also
25+
# not succeed as bare names.
26+
for name in ("get", "set", "willset", "didset"):
27+
bp = target.BreakpointCreateByName(name, "a.out")
28+
self.assertEqual(bp.num_locations, 0, f"{name} breakpoint unexpected")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct Thing {
2+
var read_only: Int { 22 + 15 }
3+
4+
var read_write: Int {
5+
get { 23 + 41 }
6+
set { print("nothing") }
7+
}
8+
9+
var observed: Int {
10+
willSet { print("willSet") }
11+
didSet { print("didSet") }
12+
}
13+
}

0 commit comments

Comments
 (0)