Handle the case where there is a user breakpoint set at the location of one of our
function call exception catching breakpoints. We need to force ourselves to stop in
that case.
<rdar://problem/13903801>
llvm-svn: 182056
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
index 0a77d0d..2b5af7c 100644
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -591,7 +591,15 @@
||(m_objc_language_runtime &&
m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
+
SetPlanComplete(false);
+
+ // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
+ // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
+ stop_info_sp->OverrideShouldStop (true);
return true;
}
diff --git a/lldb/test/expression_command/call-throws/TestCallThatThrows.py b/lldb/test/expression_command/call-throws/TestCallThatThrows.py
index 596c3ef..8a849b3 100644
--- a/lldb/test/expression_command/call-throws/TestCallThatThrows.py
+++ b/lldb/test/expression_command/call-throws/TestCallThatThrows.py
@@ -1,5 +1,5 @@
"""
-Test calling a function that hits a signal set to auto-restart, make sure the call completes.
+Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.
"""
import unittest2
@@ -7,7 +7,7 @@
import lldbutil
from lldbtest import *
-class ExprCommandWithTimeoutsTestCase(TestBase):
+class ExprCommandWithThrowTestCase(TestBase):
mydir = os.path.join("expression_command", "call-throws")
@@ -22,14 +22,14 @@
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dsym_test
def test_with_dsym(self):
- """Test calling std::String member function."""
+ """Test calling a function that throws and ObjC exception."""
self.buildDsym()
self.call_function()
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin due to ObjC test case")
@dwarf_test
def test_with_dwarf(self):
- """Test calling std::String member function."""
+ """Test calling a function that throws and ObjC exception."""
self.buildDwarf()
self.call_function()
@@ -40,7 +40,7 @@
def call_function(self):
- """Test calling function with timeout."""
+ """Test calling function that throws."""
exe_name = "a.out"
exe = os.path.join(os.getcwd(), exe_name)
@@ -86,6 +86,18 @@
self.assertTrue (value.IsValid() and value.GetError().Success() == False)
self.check_after_call()
+ # Now set the ObjC language breakpoint and make sure that doesn't interfere with the call:
+ exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeObjC, False, True)
+ self.assertTrue(exception_bkpt.GetNumLocations() > 0)
+
+ options.SetIgnoreBreakpoints(True)
+ options.SetUnwindOnError(True)
+
+ value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
+
+ self.assertTrue (value.IsValid() and value.GetError().Success() == False)
+ self.check_after_call()
+
# Now set this unwind on error to false, and make sure that we stop where the exception was thrown
options.SetUnwindOnError(False)
value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)