jingham created this revision. jingham requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
The inline initializers contribute code to the constructor(s). You will step onto them in the source view as you step through the constructor, for instance. But because their source lines are outside the function source range, lldb thought a breakpoint on the initializer line was crossing from one function to another, which file & line breakpoints don't allow. That meant if you tried to set a breakpoint on one of these lines it doesn't create any locations. This patch fixes that by asserting that if the LineEntry in one of the SymbolContexts that the search produced exactly matches the file & line specifications in the breakpoint, it has to be a valid place to set the breakpoint, and we should just set it. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D94846 Files: lldb/source/Breakpoint/BreakpointResolverFileLine.cpp lldb/test/API/lang/cpp/break-on-initializers/Makefile lldb/test/API/lang/cpp/break-on-initializers/TestBreakOnCPP11Initializers.py lldb/test/API/lang/cpp/break-on-initializers/main.cpp
Index: lldb/test/API/lang/cpp/break-on-initializers/main.cpp =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/break-on-initializers/main.cpp @@ -0,0 +1,31 @@ +#include <stdio.h> +#include <vector> + +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; +} + Index: lldb/test/API/lang/cpp/break-on-initializers/TestBreakOnCPP11Initializers.py =================================================================== --- /dev/null +++ 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") + + Index: lldb/test/API/lang/cpp/break-on-initializers/Makefile =================================================================== --- /dev/null +++ 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 Index: lldb/source/Breakpoint/BreakpointResolverFileLine.cpp =================================================================== --- lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ 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);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits