Skip to content

Commit 7e84832

Browse files
committed
[lldb] Fix swift exception breakpoint command type filtering (#4027)
Specifying a typename filter for Swift exception breakpoints has been broken when creating breakpoints from the command line. In other words, this command: ``` (lldb) breakpoint set -E swift --exception-typename MyError ``` would create a breakpoint that stopped for **any** Swift exception. The fix is a one-line fix, changing the way `m_exception_extra_args` is constructed in `CommandObjectBreakpoint`. These args are consumed in [`SwiftExceptionPrecondition::ConfigurePrecondition`](https://github.com/apple/llvm-project/blob/9509716734619d7299d296cb175e5d50f1d0a857/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp#L1524-L1531). Most of the changes included in this PR are to refactor the associated unit tests. The tests had been creating the exception breakpoint via SB API, not via command line which is why this bug wasn't caught by the tests. The tests have been updated to create exception breakpoints via both API and CLI. While editing the tests, I cleaned them up too. I also deleted a duplicate and commented-out definition of `breakpoint_set_exception_typename` in `Commands/Options.td`. rdar://75959015 (cherry picked from commit 0a70434)
1 parent 552c4f6 commit 7e84832

File tree

4 files changed

+45
-49
lines changed

4 files changed

+45
-49
lines changed

lldb/packages/Python/lldbsuite/test/lldbutil.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,19 @@ def run_break_set_by_file_colon_line(
581581

582582
return get_bpno_from_match(break_results)
583583

584+
def run_break_set_by_exception(
585+
test,
586+
language,
587+
exception_typename=None):
588+
command = 'breakpoint set -E ' + language
589+
if exception_typename:
590+
command += ' --exception-typename ' + exception_typename
591+
592+
break_results = run_break_set_command(test, command)
593+
# No call to check_breakpoint_result as there's nothing to check. In
594+
# particular, the exception breakpoint isn't yet guaranteed to be resolved.
595+
return get_bpno_from_match(break_results)
596+
584597
def run_break_set_command(test, command):
585598
"""Run the command passed in - it must be some break set variant - and analyze the result.
586599
Returns a dictionary of information gleaned from the command-line results.

lldb/source/Commands/CommandObjectBreakpoint.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed {
418418
} break;
419419

420420
case 'O':
421-
m_exception_extra_args.AppendArgument("-O");
421+
m_exception_extra_args.AppendArgument("exception-typename");
422422
m_exception_extra_args.AppendArgument(option_arg);
423423
break;
424424

lldb/source/Commands/Options.td

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,6 @@ let Command = "breakpoint set" in {
218218
def breakpoint_set_file_colon_line : Option<"joint-specifier", "y">, Group<12>, Arg<"FileLineColumn">,
219219
Required, Completion<"SourceFile">,
220220
Desc<"A specifier in the form filename:line[:column] for setting file & line breakpoints.">;
221-
/* Don't add this option till it actually does something useful...
222-
def breakpoint_set_exception_typename : Option<"exception-typename", "O">,
223-
Arg<"TypeName">, Desc<"The breakpoint will only stop if an "
224-
"exception Object of this type is thrown. Can be repeated multiple times "
225-
"to stop for multiple object types">;
226-
*/
227221
}
228222

229223
let Command = "breakpoint clear" in {

lldb/test/API/functionalities/breakpoint/swift_exception/TestExpressionErrorBreakpoint.py

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,81 +26,70 @@ class TestSwiftErrorBreakpoint(TestBase):
2626

2727
@decorators.skipIfLinux # <rdar://problem/30909618>
2828
@swiftTest
29-
def test_swift_error_no_pattern(self):
29+
def test_swift_error_no_typename(self):
3030
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
31-
self.build()
32-
self.do_test(lldb.SBStringList(), True)
31+
self.do_tests(None, True)
3332

3433
@swiftTest
35-
def test_swift_error_matching_base_pattern(self):
34+
def test_swift_error_matching_base_typename(self):
3635
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
37-
self.build()
38-
pattern = lldb.SBStringList()
39-
pattern.AppendString("exception-typename")
40-
pattern.AppendString("EnumError")
41-
self.do_test(pattern, True)
36+
self.do_tests("EnumError", True)
4237

4338
@swiftTest
44-
def test_swift_error_matching_full_pattern(self):
39+
def test_swift_error_matching_full_typename(self):
4540
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
46-
self.build()
47-
pattern = lldb.SBStringList()
48-
pattern.AppendString("exception-typename")
49-
pattern.AppendString("a.EnumError")
50-
self.do_test(pattern, True)
41+
self.do_tests("a.EnumError", True)
5142

5243
@swiftTest
53-
def test_swift_error_bogus_pattern(self):
44+
def test_swift_error_bogus_typename(self):
5445
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
55-
self.build()
56-
pattern = lldb.SBStringList()
57-
pattern.AppendString("exception-typename")
58-
pattern.AppendString("NoSuchErrorHere")
59-
self.do_test(pattern, False)
46+
self.do_tests("NoSuchErrorHere", False)
6047

6148
def setUp(self):
6249
TestBase.setUp(self)
63-
self.main_source = "main.swift"
64-
self.main_source_spec = lldb.SBFileSpec(self.main_source)
50+
self.build()
6551

66-
def do_test(self, patterns, should_stop):
67-
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
52+
def do_tests(self, typename, should_stop):
53+
self.do_test(typename, should_stop, self.create_breakpoint_with_api)
54+
self.do_test(typename, should_stop, self.create_breakpoint_with_command)
55+
56+
def create_breakpoint_with_api(self, target, typename):
57+
types = lldb.SBStringList()
58+
if typename:
59+
types.AppendString("exception-typename")
60+
types.AppendString(typename)
61+
return target.BreakpointCreateForException(
62+
lldb.eLanguageTypeSwift, False, True, types).GetID()
6863

64+
def create_breakpoint_with_command(self, target, typename):
65+
return lldbutil.run_break_set_by_exception(
66+
self, "swift", exception_typename=typename)
67+
68+
def do_test(self, typename, should_stop, make_breakpoint):
6969
exe_name = "a.out"
7070
exe = self.getBuildArtifact(exe_name)
7171

7272
# Create the target
7373
target = self.dbg.CreateTarget(exe)
74-
self.target = target
7574
self.assertTrue(target, VALID_TARGET)
7675

7776
# Set the breakpoints
78-
swift_error_bkpt = target.BreakpointCreateForException(
79-
lldb.eLanguageTypeSwift, False, True, patterns)
77+
swift_error_bkpt_id = make_breakpoint(target, typename)
8078
# Note, I'm not checking locations here because we never know them
8179
# before launch.
8280

8381
# Launch the process, and do not stop at the entry point.
8482
process = target.LaunchSimple(None, None, os.getcwd())
85-
self.process = process
8683

8784
if should_stop:
8885
self.assertTrue(process, PROCESS_IS_VALID)
89-
breakpoint_threads = lldbutil.get_threads_stopped_at_breakpoint(
90-
process, swift_error_bkpt)
91-
self.assertTrue(
92-
len(breakpoint_threads) == 1,
86+
breakpoint_threads = lldbutil.get_threads_stopped_at_breakpoint_id(
87+
process, swift_error_bkpt_id)
88+
self.assertEqual(len(breakpoint_threads), 1,
9389
"We didn't stop at the error breakpoint")
9490
else:
9591
exit_state = process.GetState()
96-
self.assertTrue(
97-
exit_state == lldb.eStateExited,
92+
self.assertEqual(exit_state, lldb.eStateExited,
9893
"We stopped at the error breakpoint when we shouldn't have.")
9994

100-
target.BreakpointDelete(swift_error_bkpt.GetID())
101-
102-
if __name__ == '__main__':
103-
import atexit
104-
lldb.SBDebugger.Initialize()
105-
atexit.register(lldb.SBDebugger.Terminate)
106-
unittest2.main()
95+
target.BreakpointDelete(swift_error_bkpt_id)

0 commit comments

Comments
 (0)