From c9a0d3be6953e5aab5d2b2e25d5904f315facc41 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Mon, 27 Jul 2015 17:03:34 +0000 Subject: [PATCH] [lldb-mi] Fix breakpoints on functions when C++ namespaces are used. The command "-break-insert ns::foo" for function 'foo' in namespace 'ns' was being parsed as file:function. This patch fixes these cases by adding checks for '::'. (Note: '::func' is not parsed correctly by lldb due to llvm.org/pr24271). Reviewed by: ki.stfu Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D11396 llvm-svn: 243281 --- lldb/test/tools/lldb-mi/breakpoint/TestMiBreak.py | 22 ++++++++++-------- lldb/tools/lldb-mi/MICmdCmdBreak.cpp | 28 +++++++++++++++++++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lldb/test/tools/lldb-mi/breakpoint/TestMiBreak.py b/lldb/test/tools/lldb-mi/breakpoint/TestMiBreak.py index 4cb253d..9c988ea 100644 --- a/lldb/test/tools/lldb-mi/breakpoint/TestMiBreak.py +++ b/lldb/test/tools/lldb-mi/breakpoint/TestMiBreak.py @@ -75,6 +75,11 @@ class MiBreakTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") + #FIXME: this test is disabled due to lldb bug llvm.org/pr24271. + # Test that we can set a BP using the global namespace token + #self.runCmd("-break-insert ::main") + #self.expect("\^done,bkpt={number=\"3\"") + @lldbmi_test @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @@ -206,21 +211,20 @@ class MiBreakTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"3\"") - # Test that the target.language=pascal setting works and that BP #5 is not set + # Test that the target.language=pascal setting works and that BP #5 is NOT set self.runCmd("-interpreter-exec console \"settings set target.language c\"") self.expect("\^done") self.runCmd("-break-insert ns.foo1") self.expect("\^error") # Test that the target.language=c++ setting works and that BP #6 is hit - # FIXME: lldb-mi interprets 'ns::func' as file:func where file='ns:'. - #self.runCmd("-interpreter-exec console \"settings set target.language c++\"") - #self.expect("\^done") - #self.runCmd("-break-insert ns::foo1") - #self.expect("\^done,bkpt={number=\"6\"") - #self.runCmd("-exec-run") - #self.expect("\^running") - #self.expect("\*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"6\"") + self.runCmd("-interpreter-exec console \"settings set target.language c++\"") + self.expect("\^done") + self.runCmd("-break-insert ns::foo1") + self.expect("\^done,bkpt={number=\"6\"") + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"6\"") # Test that BP #1 and #2 weren't set by running to program exit self.runCmd("-exec-continue") diff --git a/lldb/tools/lldb-mi/MICmdCmdBreak.cpp b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp index 3b085b3..f78aabe 100644 --- a/lldb/tools/lldb-mi/MICmdCmdBreak.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp @@ -108,6 +108,25 @@ CMICmdCmdBreakInsert::ParseArgs(void) } //++ ------------------------------------------------------------------------------------ +// Helper function for CMICmdCmdBreakInsert::Execute(void). +// +// Given a string, return the position of the ':' separator in 'file:func' +// or 'file:line', if any. If not found, return npos. For example, return +// 5 for 'foo.c:std::string'. +//-- +static size_t findFileSeparatorPos(const std::string& x) +{ + // Full paths in windows can have ':' after a drive letter, so we + // search backwards, taking care to skip C++ namespace tokens '::'. + size_t n = x.find_last_of(':'); + while (n != std::string::npos && n > 1 && x[n-1] == ':') + { + n = x.find_last_of(':', n - 2); + } + return n; +} + +//++ ------------------------------------------------------------------------------------ // Details: The invoker requires this function. The command does work in this function. // The command is likely to communicate with the LLDB SBDebugger in here. // Type: Overridden. @@ -161,17 +180,16 @@ CMICmdCmdBreakInsert::Execute(void) // Determine if break on a file line or at a function BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; - const CMIUtilString cColon = ":"; CMIUtilString fileName; MIuint nFileLine = 0; CMIUtilString strFileFn; CMIUtilString rStrLineOrFn; - // Full path in windows can have : after drive letter. So look for the - // last colon - const size_t nPosColon = m_brkName.find_last_of(cColon); + // Is the string in the form 'file:func' or 'file:line'? + // If so, find the position of the ':' separator. + const size_t nPosColon = findFileSeparatorPos(m_brkName); if (nPosColon != std::string::npos) { - // extract file name and line number from it + // Extract file name and line number from it fileName = m_brkName.substr(0, nPosColon); rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1); -- 2.7.4