diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -187,6 +187,14 @@ // is 0, then we can't do this calculation. That can happen if // GetStartLineSourceInfo gets an error, or if the first line number in // the function really is 0 - which happens for some languages. + + // But only do this calculation if the line number we found in the SC + // was different from the one requested in the source file. If we actually + // found an exact match it must be valid. + + if (m_line_number == sc.line_entry.line) + continue; + const int decl_line_is_too_late_fudge = 1; if (line && m_line_number < line - decl_line_is_too_late_fudge) { LLDB_LOG(log, "removing symbol context at {0}:{1}", file, line); diff --git a/lldb/test/API/lang/cpp/break-on-initializers/Makefile b/lldb/test/API/lang/cpp/break-on-initializers/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/break-on-initializers/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CXXFLAGS_EXTRAS := -std=c++11 + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/break-on-initializers/TestBreakOnCPP11Initializers.py b/lldb/test/API/lang/cpp/break-on-initializers/TestBreakOnCPP11Initializers.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/break-on-initializers/TestBreakOnCPP11Initializers.py @@ -0,0 +1,52 @@ +""" +When using C++11 in place member initialization, show that we +can set and hit breakpoints on initialization lines. This is a +little bit tricky because we try not to move file and line breakpoints +across function boundaries but these lines are outside the source range +of the constructor. +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class RenameThisSampleTestTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoints_on_initializers(self): + """Show we can set breakpoints on initializers appearing both before + and after the constructor body, and hit them.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + self.first_initializer_line = line_number("main.cpp", "Set the before constructor breakpoint here") + self.second_initializer_line = line_number("main.cpp", "Set the after constructor breakpoint here") + self.sample_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Set up your test case here. If your test doesn't need any set up then + # remove this method from your TestCase class. + + def sample_test(self): + """You might use the test implementation in several ways, say so here.""" + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + " Set a breakpoint here to get started", self.main_source_file) + + # Now set breakpoints on the two initializer lines we found in the test startup: + bkpt1 = target.BreakpointCreateByLocation(self.main_source_file, self.first_initializer_line) + self.assertEqual(bkpt1.GetNumLocations(), 1) + bkpt2 = target.BreakpointCreateByLocation(self.main_source_file, self.second_initializer_line) + self.assertEqual(bkpt2.GetNumLocations(), 1) + + # Now continue, we should stop at the two breakpoints above, first the one before, then + # the one after. + self.assertEqual(len(lldbutil.continue_to_breakpoint(process, bkpt1)), 1, "Hit first breakpoint") + self.assertEqual(len(lldbutil.continue_to_breakpoint(process, bkpt2)), 1, "Hit second breakpoint") + + diff --git a/lldb/test/API/lang/cpp/break-on-initializers/main.cpp b/lldb/test/API/lang/cpp/break-on-initializers/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/break-on-initializers/main.cpp @@ -0,0 +1,31 @@ +#include +#include + +class Trivial { +public: + Trivial(int input) : m_int(input) {} +private: + int m_int; + +}; + +class Foo { +private: + Trivial m_trivial = Trivial(100); // Set the before constructor breakpoint here + +public: + Foo(int input) { + printf("I have been made!\n"); + } + +private: + Trivial m_other_trivial = Trivial(200); // Set the after constructor breakpoint here +}; + +int +main() +{ + Foo myFoo(10); // Set a breakpoint here to get started + return 0; +} +