Skip to content

Commit 6f94d99

Browse files
author
git apple-llvm automerger
committed
Merge commit '65f254710438' from swift/release/5.9 into stable/20221013
2 parents c87088f + 65f2547 commit 6f94d99

File tree

5 files changed

+122
-1
lines changed

5 files changed

+122
-1
lines changed

lldb/include/lldb/Target/Process.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,13 @@ class ProcessModID {
287287
return m_resume_id == m_last_user_expression_resume;
288288
}
289289

290+
bool IsRunningExpression() const {
291+
// Don't return true if we are no longer running an expression:
292+
if (m_running_user_expression || m_running_utility_function)
293+
return true;
294+
return false;
295+
}
296+
290297
void SetRunningUserExpression(bool on) {
291298
if (on)
292299
m_running_user_expression++;

lldb/source/Target/StopInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ class StopInfoBreakpoint : public StopInfo {
332332

333333
ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
334334
Process *process = exe_ctx.GetProcessPtr();
335-
if (process->GetModIDRef().IsLastResumeForUserExpression()) {
335+
if (process->GetModIDRef().IsRunningExpression()) {
336336
// If we are in the middle of evaluating an expression, don't run
337337
// asynchronous breakpoint commands or expressions. That could
338338
// lead to infinite recursion if the command or condition re-calls
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
OBJC_SOURCES := main.m
2+
LD_EXTRAS := -framework Foundation
3+
4+
include Makefile.rules
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Test that the built in ObjC exception throw recognizer works
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.decorators import *
7+
import lldbsuite.test.lldbutil as lldbutil
8+
from lldbsuite.test.lldbtest import *
9+
10+
class TestObjCRecognizer(TestBase):
11+
12+
NO_DEBUG_INFO_TESTCASE = True
13+
14+
@skipUnlessDarwin
15+
def test_exception_recognizer_sub_class(self):
16+
"""There can be many tests in a test case - describe this test here."""
17+
self.build()
18+
self.main_source_file = lldb.SBFileSpec("main.m")
19+
self.objc_recognizer_test(True)
20+
21+
@skipUnlessDarwin
22+
def test_exception_recognizer_plain(self):
23+
"""There can be many tests in a test case - describe this test here."""
24+
self.build()
25+
self.main_source_file = lldb.SBFileSpec("main.m")
26+
self.objc_recognizer_test(False)
27+
28+
def objc_recognizer_test(self, sub_class):
29+
"""Make sure we stop at the exception and get all the fields out of the recognizer.
30+
If sub_class is True, we make a subclass of NSException and throw that."""
31+
if sub_class:
32+
bkpt_string = "Set a breakpoint here for MyException"
33+
else:
34+
bkpt_string = "Set a breakpoint here for plain exception"
35+
36+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
37+
bkpt_string, self.main_source_file)
38+
39+
# Now turn on the ObjC Exception breakpoint and continue to hit it:
40+
exception_bkpt = target.BreakpointCreateForException(lldb.eLanguageTypeObjC, False, True)
41+
self.assertTrue(exception_bkpt.GetNumLocations() > 0, "Got some exception locations")
42+
43+
threads = lldbutil.continue_to_breakpoint(process, exception_bkpt)
44+
self.assertEqual(len(threads), 1, "One thread hit exception breakpoint")
45+
frame = threads[0].frame[0]
46+
47+
# This test relies on the dereference argument to ValueCheck, which isn't on
48+
# this branch, so I'm skipping that portion of the test.
49+
return
50+
51+
var_opts = lldb.SBVariablesOptions()
52+
var_opts.SetIncludeRecognizedArguments(True)
53+
var_opts.SetUseDynamic(True)
54+
vars = frame.GetVariables(var_opts)
55+
self.assertEqual(len(vars), 1, "Got the synthetic argument")
56+
self.assertTrue(vars[0].IsValid(), "Got a valid Exception variable")
57+
58+
# This will be a pointer
59+
60+
ns_exception_children = [ValueCheck(type="NSObject"),
61+
ValueCheck(name="name", summary='"NSException"'),
62+
ValueCheck(name="reason", summary='"Simple Reason"'),
63+
ValueCheck(name="userInfo"),
64+
ValueCheck(name="reserved")]
65+
ns_exception = ValueCheck(type="NSException", children=ns_exception_children)
66+
if not sub_class:
67+
simple_check = ValueCheck(name="exception", dereference=ns_exception)
68+
simple_check.check_value(self, vars[0], "Simple exception is right")
69+
else:
70+
my_exception_children = [ns_exception, ValueCheck(name="extra_info", type="int", value="100")]
71+
my_exception = ValueCheck(type="MyException", children=my_exception_children)
72+
sub_check = ValueCheck(name="exception", type="MyException *", dereference=my_exception)
73+
sub_check.check_value(self, vars[0], "Subclass exception is right")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface MyException : NSException
4+
{
5+
int extra_info;
6+
}
7+
- (NSException *) initWithExtraInfo: (int) info;
8+
@end
9+
10+
@implementation MyException
11+
- (NSException *) initWithExtraInfo: (int) info
12+
{
13+
[super initWithName: @"NSException" reason: @"Simple Reason" userInfo: nil];
14+
self->extra_info = info;
15+
return self;
16+
}
17+
@end
18+
19+
int
20+
main(int argc, char **argv)
21+
{
22+
// Set a breakpoint here for plain exception:
23+
@try {
24+
NSException *plain_exc = [[NSException alloc] initWithName: @"NSException" reason: @"Simple Reason" userInfo: nil];
25+
[plain_exc raise];
26+
}
27+
@catch (id anException) {}
28+
29+
// Set a breakpoint here for MyException:
30+
@try {
31+
MyException *my_exc = [[MyException alloc] initWithExtraInfo: 100];
32+
[my_exc raise];
33+
}
34+
@catch (id anException) {}
35+
36+
return 0;
37+
}

0 commit comments

Comments
 (0)