Skip to content

Commit dc3eba2

Browse files
committed
[lldb] Support typed throws for Swift exception breakpoints
Swift typed throws [SE 0413][1] use a new breakpoint hook: `swift_willThrowTypedImpl`. This is separate from the hook already used for untyped throws: `swift_willThrow`. This change supports stopping on the new throw hook. However this change does not support typename filtering, which will require additional changes because `swift_willThrowTypedImpl` is called differently from `swift_willThrow`. In the new hook, the exception is passed piecewise as parameters, rather than through a dedicated register. The changes will be made to `SwiftLanguageRuntime::CalculateErrorValue`. rdar://148033200 [1]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md "Typed throws" (cherry-picked from commit c5dd0ec)
1 parent 63fb3f6 commit dc3eba2

File tree

3 files changed

+44
-76
lines changed

3 files changed

+44
-76
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,11 @@ static lldb::BreakpointResolverSP
280280
CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp, bool throw_bp) {
281281
BreakpointResolverSP resolver_sp;
282282

283+
static const char *names[] = {"swift_willThrow", "swift_willThrowTypedImpl"};
283284
if (throw_bp)
284-
resolver_sp.reset(new BreakpointResolverName(
285-
bkpt, "swift_willThrow", eFunctionNameTypeBase, eLanguageTypeUnknown,
286-
Breakpoint::Exact, 0, eLazyBoolNo));
285+
resolver_sp.reset(
286+
new BreakpointResolverName(bkpt, names, 2, eFunctionNameTypeBase,
287+
eLanguageTypeUnknown, 0, eLazyBoolNo));
287288
// FIXME: We don't do catch breakpoints for ObjC yet.
288289
// Should there be some way for the runtime to specify what it can do in this
289290
// regard?

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,40 @@ class TestSwiftErrorBreakpoint(TestBase):
2525
def test_swift_error_no_typename(self):
2626
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
2727
self.build()
28-
self.do_tests(None, True)
28+
self.do_tests(None)
2929

3030
@swiftTest
3131
def test_swift_error_matching_base_typename(self):
3232
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
3333
self.build()
34-
self.do_tests("EnumError", True)
34+
self.do_tests("EnumError")
3535

3636
@swiftTest
3737
def test_swift_error_matching_full_typename(self):
3838
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
3939
self.build()
40-
self.do_tests("a.EnumError", True)
40+
self.do_tests("a.EnumError")
4141

4242
@swiftTest
4343
def test_swift_error_bogus_typename(self):
4444
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
4545
self.build()
46-
self.do_tests("NoSuchErrorHere", False)
46+
self.do_tests_in_mode("NoSuchErrorHere", mode="untyped", should_stop=False)
4747

48-
def setUp(self):
49-
TestBase.setUp(self)
48+
@swiftTest
49+
@expectedFailureAll(bugnumber="rdar://148033473")
50+
def test_swift_typed_error_bogus_typename(self):
51+
"""Tests that swift error throws are correctly caught by the Swift Error breakpoint"""
52+
self.build()
53+
self.do_tests_in_mode("NoSuchErrorHere", mode="typed", should_stop=False)
54+
55+
def do_tests(self, typename, should_stop=True):
56+
for mode in ("typed", "untyped"):
57+
self.do_tests_in_mode(typename, mode, should_stop)
5058

51-
def do_tests(self, typename, should_stop):
52-
self.do_test(typename, should_stop, self.create_breakpoint_with_api)
53-
self.do_test(typename, should_stop, self.create_breakpoint_with_command)
59+
def do_tests_in_mode(self, typename, mode, should_stop):
60+
self.do_test(typename, mode, should_stop, self.create_breakpoint_with_api)
61+
self.do_test(typename, mode, should_stop, self.create_breakpoint_with_command)
5462

5563
def create_breakpoint_with_api(self, target, typename):
5664
types = lldb.SBStringList()
@@ -64,7 +72,7 @@ def create_breakpoint_with_command(self, target, typename):
6472
return lldbutil.run_break_set_by_exception(
6573
self, "swift", exception_typename=typename)
6674

67-
def do_test(self, typename, should_stop, make_breakpoint):
75+
def do_test(self, typename, mode, should_stop, make_breakpoint):
6876
exe_name = "a.out"
6977
exe = self.getBuildArtifact(exe_name)
7078

@@ -78,7 +86,7 @@ def do_test(self, typename, should_stop, make_breakpoint):
7886
# before launch.
7987

8088
# Launch the process, and do not stop at the entry point.
81-
process = target.LaunchSimple(None, None, os.getcwd())
89+
process = target.LaunchSimple([mode], None, os.getcwd())
8290

8391
if should_stop:
8492
self.assertTrue(process, PROCESS_IS_VALID)
Lines changed: 21 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,35 @@
1-
// main.swift
2-
//
3-
// This source file is part of the Swift.org open source project
4-
//
5-
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6-
// Licensed under Apache License v2.0 with Runtime Library Exception
7-
//
8-
// See https://swift.org/LICENSE.txt for license information
9-
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10-
//
11-
// -----------------------------------------------------------------------------
12-
enum EnumError : Error
13-
{
14-
case ImportantError
1+
enum EnumError: Error {
152
case TrivialError
3+
case ImportantError
164
}
175

18-
class ClassError : Error
19-
{
20-
var _code : Int = 10
21-
var _domain : String = "ClassError"
22-
var m_message : String
23-
24-
init (_ message: String)
25-
{
26-
m_message = message
27-
}
28-
func SomeMethod (_ input : Int)
29-
{
30-
print (m_message) // Set a breakpoint here to test method contexts
31-
}
32-
}
33-
34-
func IThrowEnumOver10(_ input : Int) throws -> Int
35-
{
36-
if input > 100
37-
{
6+
func untyped(_ input : Int) throws -> Int {
7+
if input > 100 {
388
throw EnumError.ImportantError
39-
}
40-
else if input > 10
41-
{
9+
} else if input > 10 {
4210
throw EnumError.TrivialError
43-
}
44-
else
45-
{
11+
} else {
4612
return input + 2
4713
}
4814
}
4915

50-
func IThrowObjectOver10(_ input : Int) throws -> Int
51-
{
52-
if input > 100
53-
{
54-
let my_error = ClassError("Over 100")
55-
throw my_error
56-
}
57-
else if input > 10
58-
{
59-
let my_error = ClassError("Over 10 but less than 100")
60-
throw my_error
61-
}
62-
else
63-
{
16+
func typed(_ input : Int) throws(EnumError) -> Int {
17+
if input > 100 {
18+
throw EnumError.ImportantError
19+
} else if input > 10 {
20+
throw EnumError.TrivialError
21+
} else {
6422
return input + 2
6523
}
6624
}
6725

68-
do
69-
{
70-
try IThrowEnumOver10(101) // Set a breakpoint here to run expressions
71-
try IThrowObjectOver10(11)
72-
}
73-
catch (let e)
74-
{
75-
print (e, true)
26+
do {
27+
let mode = CommandLine.arguments[1]
28+
if mode == "untyped" {
29+
try untyped(101)
30+
} else if mode == "typed" {
31+
try typed(101)
32+
}
33+
} catch {
34+
print(error)
7635
}

0 commit comments

Comments
 (0)