[Lldb-commits] [lldb] [llvm] [lldb][SBAPI] Add (SBTarget/SBModule)::FindSymbolContexts (PR #223808)
Ebuka Ezike via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 15 13:08:58 PDT 2026
https://github.com/da-viper created https://github.com/llvm/llvm-project/pull/223808
Add two new SBAPI methods that return every symbol context matching a source location.
* SBTarget::FindSymbolContexts(SBLineEntry, resolve_scope, check_inlines) searches across every module in the target.
* SBModule::FindSymbolContexts(SBLineEntry, resolve_scope, check_inlines) searches within one module.
Both return an SBSymbolContextList. I intend to use the API in the `gotoTargets` request in lldb-dap to get the locations we can jump to. See https://github.com/llvm/llvm-project/pull/130503#discussion_r2015102408
A SBLineEntry(SBFileSpec, line, column) constructor lets scripts build the location argument directly.
I don't like doing the below to make a line entry.
```py
line_entry = lldb.SBLineEntry()
line_entry.SetFileSpec(filespec)
line_entry.SetLine(line)
line_entry.SetColumn(column)
```
SBLineEntry::GetLine() and GetColumn() now return
LLDB_INVALID_LINE_NUMBER / LLDB_INVALID_COLUMN_NUMBER respectively.
>From 2d23ac9ae73778786e2eea8fcee909b08604664b Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <e_ezike at apple.com>
Date: Tue, 15 Sep 2026 21:04:28 +0100
Subject: [PATCH] [lldb][SBAPI] Add (SBTarget/SBModule)::FindSymbolContexts
Add two new SBAPI methods that return every symbol context matching a
source location.
* SBTarget::FindSymbolContexts(SBLineEntry, resolve_scope, check_inlines)
searches across every module in the target.
* SBModule::FindSymbolContexts(SBLineEntry, resolve_scope, check_inlines)
searches within one module.
Both return an SBSymbolContextList. I intend to use the API in the
`gotoTargets` request in lldb-dap to get the locations we can jump to.
See https://github.com/llvm/llvm-project/pull/130503#discussion_r2015102408
A SBLineEntry(SBFileSpec, line, column) constructor lets scripts
build the location argument directly.
I don't like doing the below to make a line entry.
```py
line_entry = lldb.SBLineEntry()
line_entry.SetFileSpec(filespec)
line_entry.SetLine(line)
line_entry.SetColumn(column)
```
SBLineEntry::GetLine() and GetColumn() now return
LLDB_INVALID_LINE_NUMBER / LLDB_INVALID_COLUMN_NUMBER respectively.
---
.../interface/SBLineEntryDocstrings.i | 3 +
lldb/bindings/interface/SBModuleDocstrings.i | 3 +
lldb/bindings/interface/SBTargetDocstrings.i | 3 +
lldb/include/lldb/API/SBLineEntry.h | 5 +
lldb/include/lldb/API/SBModule.h | 24 +++
lldb/include/lldb/API/SBTarget.h | 25 +++
lldb/source/API/SBLineEntry.cpp | 18 ++-
lldb/source/API/SBModule.cpp | 21 +++
lldb/source/API/SBTarget.cpp | 22 +++
.../python_api/find_symbol_contexts/Makefile | 3 +
.../TestFindSymbolContexts.py | 150 ++++++++++++++++++
.../python_api/find_symbol_contexts/inlined.h | 19 +++
.../python_api/find_symbol_contexts/main.cpp | 6 +
.../python_api/sblineentry/TestSBLineEntry.py | 50 ++++--
lldb/unittests/API/SBLineEntryTest.cpp | 11 +-
llvm/docs/ReleaseNotes.md | 7 +
16 files changed, 357 insertions(+), 13 deletions(-)
create mode 100644 lldb/test/API/python_api/find_symbol_contexts/Makefile
create mode 100644 lldb/test/API/python_api/find_symbol_contexts/TestFindSymbolContexts.py
create mode 100644 lldb/test/API/python_api/find_symbol_contexts/inlined.h
create mode 100644 lldb/test/API/python_api/find_symbol_contexts/main.cpp
diff --git a/lldb/bindings/interface/SBLineEntryDocstrings.i b/lldb/bindings/interface/SBLineEntryDocstrings.i
index 1a3aa48d31ffc..f4115d2227128 100644
--- a/lldb/bindings/interface/SBLineEntryDocstrings.i
+++ b/lldb/bindings/interface/SBLineEntryDocstrings.i
@@ -28,3 +28,6 @@ produces: ::
See also :py:class:`SBCompileUnit` ."
) lldb::SBLineEntry;
+
+// Emit one Python wrapper for the default-argument overload.
+%feature("compactdefaultargs") lldb::SBLineEntry::SBLineEntry;
diff --git a/lldb/bindings/interface/SBModuleDocstrings.i b/lldb/bindings/interface/SBModuleDocstrings.i
index 289cf5335de62..fa1c9fb9f1bb2 100644
--- a/lldb/bindings/interface/SBModuleDocstrings.i
+++ b/lldb/bindings/interface/SBModuleDocstrings.i
@@ -212,3 +212,6 @@ produces this following output: ::
relied upon. Use SBDebugger::MemoryPressureDetected instead to reduce
LLDB's memory consumption during execution.
") lldb::SBModule::GarbageCollectAllocatedModules;
+
+// Emit one Python wrapper for the default-argument overload.
+%feature("compactdefaultargs") lldb::SBModule::FindSymbolContexts;
diff --git a/lldb/bindings/interface/SBTargetDocstrings.i b/lldb/bindings/interface/SBTargetDocstrings.i
index de03f8ea24b40..dac18e9fef77f 100644
--- a/lldb/bindings/interface/SBTargetDocstrings.i
+++ b/lldb/bindings/interface/SBTargetDocstrings.i
@@ -541,3 +541,6 @@ produces: ::
:rtype: bool
"
) lldb::SBTarget::IsLoaded;
+
+// Emit one Python wrapper for the default-argument overload.
+%feature("compactdefaultargs") lldb::SBTarget::FindSymbolContexts;
diff --git a/lldb/include/lldb/API/SBLineEntry.h b/lldb/include/lldb/API/SBLineEntry.h
index d70c4fac6ec71..c9b4dd10a597e 100644
--- a/lldb/include/lldb/API/SBLineEntry.h
+++ b/lldb/include/lldb/API/SBLineEntry.h
@@ -12,6 +12,7 @@
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBFileSpec.h"
+#include "lldb/lldb-defines.h"
namespace lldb {
@@ -19,6 +20,10 @@ class LLDB_API SBLineEntry {
public:
SBLineEntry();
+ SBLineEntry(const lldb::SBFileSpec &filespec,
+ uint32_t line = LLDB_INVALID_LINE_NUMBER,
+ uint32_t column = LLDB_INVALID_COLUMN_NUMBER);
+
SBLineEntry(const lldb::SBLineEntry &rhs);
~SBLineEntry();
diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h
index 4bd3e899d154d..9f0ca8692cfc9 100644
--- a/lldb/include/lldb/API/SBModule.h
+++ b/lldb/include/lldb/API/SBModule.h
@@ -137,6 +137,30 @@ class LLDB_API SBModule {
lldb::SBSymbolContextList
FindCompileUnits(const lldb::SBFileSpec &sb_file_spec);
+ /// Find every symbol context in this module that maps to the source
+ /// location in \a line_entry. Each returned `SBSymbolContext` carries the
+ /// module, compile unit, function, block, and line entry for one match.
+ ///
+ /// \param[in] line_entry
+ /// The source location to resolve.
+ ///
+ /// \param[in] resolve_scope
+ /// A bitmask of `lldb::SymbolContextItem` values selecting which
+ /// fields of each returned `SBSymbolContext` are populated. Defaults
+ /// to `eSymbolContextEverything`.
+ ///
+ /// \param[in] check_inlines
+ /// If true, also return inlined instances of the source file that live
+ /// in other compile units.
+ ///
+ /// \return
+ /// A list of matching symbol contexts, or an empty list if this module
+ /// has no debug info for the requested location.
+ lldb::SBSymbolContextList FindSymbolContexts(
+ const lldb::SBLineEntry &line_entry,
+ lldb::SymbolContextItem resolve_scope = lldb::eSymbolContextEverything,
+ bool check_inlines = true);
+
size_t GetNumSymbols();
lldb::SBSymbol GetSymbolAtIndex(size_t idx);
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index 84cbcfb4e69d2..902a86d4f0fb2 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -353,6 +353,31 @@ class LLDB_API SBTarget {
lldb::SBSymbolContextList
FindCompileUnits(const lldb::SBFileSpec &sb_file_spec);
+ /// Find every symbol context in this target's modules that maps to the
+ /// source location in \a line_entry. Each returned `SBSymbolContext`
+ /// carries the module, compile unit, function, block, and line entry for
+ /// one match.
+ ///
+ /// \param[in] line_entry
+ /// The source location to resolve.
+ ///
+ /// \param[in] resolve_scope
+ /// A bitmask of `lldb::SymbolContextItem` values selecting which
+ /// fields of each returned `SBSymbolContext` are populated. Defaults
+ /// to `eSymbolContextEverything`.
+ ///
+ /// \param[in] check_inlines
+ /// If true, also return inlined instances of the source file that live
+ /// in other compile units.
+ ///
+ /// \return
+ /// A list of matching symbol contexts, or an empty list if no module
+ /// in this target has debug info for the requested location.
+ lldb::SBSymbolContextList FindSymbolContexts(
+ const lldb::SBLineEntry &line_entry,
+ lldb::SymbolContextItem resolve_scope = lldb::eSymbolContextEverything,
+ bool check_inlines = true);
+
lldb::ByteOrder GetByteOrder();
uint32_t GetAddressByteSize();
diff --git a/lldb/source/API/SBLineEntry.cpp b/lldb/source/API/SBLineEntry.cpp
index 22572941fccbd..b16e78231054b 100644
--- a/lldb/source/API/SBLineEntry.cpp
+++ b/lldb/source/API/SBLineEntry.cpp
@@ -13,14 +13,28 @@
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-defines.h"
#include <climits>
+#include <memory>
using namespace lldb;
using namespace lldb_private;
SBLineEntry::SBLineEntry() { LLDB_INSTRUMENT_VA(this); }
+SBLineEntry::SBLineEntry(const SBFileSpec &filespec, uint32_t line,
+ uint32_t column)
+ : m_opaque_up(std::make_unique<LineEntry>()) {
+ LLDB_INSTRUMENT_VA(this, filespec, line, column);
+
+ SetFileSpec(filespec);
+ if (line != LLDB_INVALID_LINE_NUMBER)
+ SetLine(line);
+ if (column != LLDB_INVALID_COLUMN_NUMBER)
+ SetColumn(column);
+}
+
SBLineEntry::SBLineEntry(const SBLineEntry &rhs) {
LLDB_INSTRUMENT_VA(this, rhs);
@@ -105,7 +119,7 @@ SBFileSpec SBLineEntry::GetFileSpec() const {
uint32_t SBLineEntry::GetLine() const {
LLDB_INSTRUMENT_VA(this);
- uint32_t line = 0;
+ uint32_t line = LLDB_INVALID_LINE_NUMBER;
if (m_opaque_up)
line = m_opaque_up->line;
@@ -117,7 +131,7 @@ uint32_t SBLineEntry::GetColumn() const {
if (m_opaque_up)
return m_opaque_up->column;
- return 0;
+ return LLDB_INVALID_COLUMN_NUMBER;
}
void SBLineEntry::SetFileSpec(lldb::SBFileSpec filespec) {
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp
index d9a427d7e5d0c..d6a401914b50f 100644
--- a/lldb/source/API/SBModule.cpp
+++ b/lldb/source/API/SBModule.cpp
@@ -290,6 +290,27 @@ SBSymbolContextList SBModule::FindCompileUnits(const SBFileSpec &sb_file_spec) {
return sb_sc_list;
}
+SBSymbolContextList
+SBModule::FindSymbolContexts(const SBLineEntry &line_entry,
+ lldb::SymbolContextItem resolve_scope,
+ bool check_inlines) {
+ LLDB_INSTRUMENT_VA(this, line_entry, resolve_scope, check_inlines);
+
+ SBSymbolContextList sc_list;
+ const ModuleSP module_sp(GetSP());
+ if (!module_sp || !line_entry.IsValid())
+ return sc_list;
+
+ SBFileSpec file_spec = line_entry.GetFileSpec();
+ if (!file_spec.IsValid())
+ return sc_list;
+
+ // TODO: Pass the column when ResolveSymbolContextsForFileSpec supports it.
+ module_sp->ResolveSymbolContextsForFileSpec(
+ *file_spec, line_entry.GetLine(), check_inlines, resolve_scope, *sc_list);
+ return sc_list;
+}
+
static Symtab *GetUnifiedSymbolTable(const lldb::ModuleSP &module_sp) {
if (module_sp)
return module_sp->GetSymtab();
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index b6ee17091ef6b..7a8d01c0e63a8 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -13,6 +13,7 @@
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBModule.h"
#include "lldb/API/SBModuleSpec.h"
@@ -1687,6 +1688,27 @@ SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
return sb_sc_list;
}
+SBSymbolContextList
+SBTarget::FindSymbolContexts(const SBLineEntry &line_entry,
+ lldb::SymbolContextItem resolve_scope,
+ bool check_inlines) {
+ LLDB_INSTRUMENT_VA(this, line_entry, resolve_scope, check_inlines);
+
+ SBSymbolContextList sc_list;
+ TargetSP target_sp = GetSP();
+ if (!target_sp || !line_entry.IsValid())
+ return sc_list;
+
+ SBFileSpec file_spec = line_entry.GetFileSpec();
+ if (!file_spec.IsValid())
+ return sc_list;
+
+ // TODO: Pass column when ResolveSymbolContextsForFileSpec supports it.
+ target_sp->GetImages().ResolveSymbolContextsForFileSpec(
+ *file_spec, line_entry.GetLine(), check_inlines, resolve_scope, *sc_list);
+ return sc_list;
+}
+
lldb::ByteOrder SBTarget::GetByteOrder() {
LLDB_INSTRUMENT_VA(this);
diff --git a/lldb/test/API/python_api/find_symbol_contexts/Makefile b/lldb/test/API/python_api/find_symbol_contexts/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/python_api/find_symbol_contexts/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/find_symbol_contexts/TestFindSymbolContexts.py b/lldb/test/API/python_api/find_symbol_contexts/TestFindSymbolContexts.py
new file mode 100644
index 0000000000000..22b06ddfd9498
--- /dev/null
+++ b/lldb/test/API/python_api/find_symbol_contexts/TestFindSymbolContexts.py
@@ -0,0 +1,150 @@
+"""Test SBTarget::FindSymbolContexts / SBModule::FindSymbolContexts APIs."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class FindSymbolContextsAPITestCase(TestBase):
+ def test_finds_inlined_header_entry(self):
+ """
+ `FindSymbolContexts` should return the inlined instance of a
+ header-defined function even though the header is not the caller's
+ compile unit. The pre-existing `SBCompileUnit::GetLineEntryAtIndex`
+ walk cannot see those entries.
+ """
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ self.assertTrue(target, VALID_TARGET)
+
+ header_spec = lldb.SBFileSpec("inlined.h")
+ inlined_line = line_number("inlined.h", "// inlined body")
+
+ sb_line_entry = lldb.SBLineEntry(header_spec, inlined_line)
+ sc_list: lldb.SBSymbolContextList = target.FindSymbolContexts(sb_line_entry)
+ self.assertGreater(sc_list.GetSize(), 0)
+
+ for sc in sc_list:
+ self.assertTrue(sc.GetModule().IsValid())
+ self.assertTrue(sc.GetCompileUnit().IsValid())
+ self.assertTrue(sc.GetFunction().IsValid())
+ entry = sc.GetLineEntry()
+ self.assertTrue(entry.IsValid())
+ self.assertEqual(entry.GetLine(), inlined_line)
+ self.assertEqual(entry.GetFileSpec().GetFilename(), "inlined.h")
+
+ def test_resolve_scope_narrows_result(self):
+ """
+ A narrower resolve_scope populates only the requested field(s).
+
+ eSymbolContextCompUnit must always be in the mask: the DWARF
+ resolver gates its compile-unit walk on that bit
+ (SymbolFileDWARF::ResolveSymbolContext), so without it no matches
+ are produced at all.
+ """
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ src_location = lldb.SBLineEntry(
+ lldb.SBFileSpec("main.cpp"),
+ line_number("main.cpp", "// break here"),
+ )
+
+ comp_unit_only = target.FindSymbolContexts(
+ src_location, lldb.eSymbolContextCompUnit
+ )
+ self.assertGreater(comp_unit_only.GetSize(), 0)
+ for sc in comp_unit_only:
+ self.assertTrue(sc.GetCompileUnit().IsValid())
+
+ with_line_entry = target.FindSymbolContexts(
+ src_location,
+ lldb.eSymbolContextCompUnit | lldb.eSymbolContextLineEntry,
+ )
+ self.assertGreater(with_line_entry.GetSize(), 0)
+ for sc in with_line_entry:
+ self.assertTrue(sc.GetCompileUnit().IsValid())
+ self.assertTrue(sc.GetLineEntry().IsValid())
+
+ with_function = target.FindSymbolContexts(
+ src_location,
+ lldb.eSymbolContextCompUnit | lldb.eSymbolContextFunction,
+ )
+ self.assertGreater(with_function.GetSize(), 0)
+ for sc in with_function:
+ self.assertTrue(sc.GetCompileUnit().IsValid())
+ self.assertTrue(sc.GetFunction().IsValid())
+
+ def test_check_inlines_false(self):
+ """check_inlines=False excludes header inlines when the header is not a primary compile unit."""
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ header_spec = lldb.SBFileSpec("inlined.h")
+ inlined_line = line_number("inlined.h", "// inlined body")
+
+ sc_list = target.FindSymbolContexts(
+ lldb.SBLineEntry(header_spec, inlined_line),
+ lldb.eSymbolContextEverything,
+ False,
+ )
+ self.assertEqual(sc_list.GetSize(), 0)
+
+ def test_primary_source(self):
+ """Both check_inlines values return matches for a primary-CU line."""
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ main_spec = lldb.SBFileSpec("main.cpp")
+ break_line = line_number("main.cpp", "// break here")
+
+ for check_inlines in (True, False):
+ sc_list = target.FindSymbolContexts(
+ lldb.SBLineEntry(main_spec, break_line),
+ lldb.eSymbolContextEverything,
+ check_inlines,
+ )
+ self.assertGreater(sc_list.GetSize(), 0, f"check_inlines={check_inlines}")
+
+ def test_matches_between_target_and_module(self):
+ """SBTarget and SBModule return the same matches for a single-module executable."""
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+
+ main_spec = lldb.SBFileSpec("main.cpp")
+ break_line = line_number("main.cpp", "// break here")
+ source_location = lldb.SBLineEntry(main_spec, break_line)
+
+ target_list = target.FindSymbolContexts(source_location)
+ self.assertGreater(target_list.GetSize(), 0)
+
+ module = target.FindModule(lldb.SBFileSpec("a.out"))
+ self.assertTrue(module.IsValid())
+ module_list = module.FindSymbolContexts(source_location)
+ self.assertEqual(target_list.GetSize(), module_list.GetSize())
+
+ def test_invalid_inputs(self):
+ """Invalid inputs returns an empty result."""
+ self.build()
+ target, *_ = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ # Default SBLineEntry.
+ empty_entry = lldb.SBLineEntry()
+ self.assertFalse(empty_entry.IsValid())
+ self.assertEqual(target.FindSymbolContexts(empty_entry).GetSize(), 0)
+
+ empty_result = target.FindSymbolContexts(lldb.SBLineEntry(lldb.SBFileSpec(), 1))
+ self.assertEqual(empty_result.GetSize(), 0)
+
+ missing_line = lldb.SBLineEntry(lldb.SBFileSpec("main.cpp"))
+ missing_result = target.FindSymbolContexts(missing_line)
+ self.assertEqual(missing_result.GetSize(), 0)
diff --git a/lldb/test/API/python_api/find_symbol_contexts/inlined.h b/lldb/test/API/python_api/find_symbol_contexts/inlined.h
new file mode 100644
index 0000000000000..73b477a60cd8e
--- /dev/null
+++ b/lldb/test/API/python_api/find_symbol_contexts/inlined.h
@@ -0,0 +1,19 @@
+#ifndef INLINED_H
+#define INLINED_H
+
+#if defined(__clang__)
+#define ALWAYS_INLINE [[clang::always_inline]] inline
+#elif defined(_MSC_VER)
+#define ALWAYS_INLINE __forceinline
+#elif defined(__GNUC__)
+#define ALWAYS_INLINE __attribute__((always_inline)) inline
+#else
+#define ALWAYS_INLINE inline
+#endif
+
+ALWAYS_INLINE int inlined_add(int a, int b) {
+ int sum = a + b; // inlined body
+ return sum;
+}
+
+#endif
diff --git a/lldb/test/API/python_api/find_symbol_contexts/main.cpp b/lldb/test/API/python_api/find_symbol_contexts/main.cpp
new file mode 100644
index 0000000000000..97810a3cad738
--- /dev/null
+++ b/lldb/test/API/python_api/find_symbol_contexts/main.cpp
@@ -0,0 +1,6 @@
+#include "inlined.h"
+
+int main(int argc, char const *argv[]) {
+ int result = inlined_add(argc, 42); // break here
+ return result - result;
+}
diff --git a/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py b/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py
index ee8404c6b8560..33e44688c7b68 100644
--- a/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py
+++ b/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py
@@ -81,22 +81,52 @@ def test_line_entry_validity_without_address(self):
self.assertFalse(line_entry.GetStartAddress().IsValid())
self.assertFalse(line_entry.GetEndAddress().IsValid())
- def test_line_entry_column(self):
- """Test setting and getting column information on synthetic line entries."""
+ def test_line_entry_line_and_column(self):
+ """Test setting and getting line and column information on synthetic line entries."""
line_entry = lldb.SBLineEntry()
- line_entry.SetLine(50)
-
- # Default column should be 0.
- self.assertEqual(line_entry.GetColumn(), 0)
-
- # Set column.
- line_entry.SetColumn(25)
- self.assertEqual(line_entry.GetColumn(), 25)
+ # Default line and column should be invalid.
+ self.assertEqual(line_entry.GetLine(), lldb.LLDB_INVALID_LINE_NUMBER)
+ self.assertEqual(line_entry.line, lldb.LLDB_INVALID_LINE_NUMBER)
+ self.assertEqual(line_entry.GetColumn(), lldb.LLDB_INVALID_COLUMN_NUMBER)
+ self.assertEqual(line_entry.column, lldb.LLDB_INVALID_COLUMN_NUMBER)
+
+ # Set line and column.
+ line = 50
+ column = 25
+ line_entry.SetLine(line)
+ line_entry.SetColumn(column)
+
+ # Verify line and column.
+ self.assertEqual(line_entry.GetLine(), line)
+ self.assertEqual(line_entry.line, line)
+ self.assertEqual(line_entry.GetColumn(), column)
+ self.assertEqual(line_entry.column, column)
# Verify line entry is still valid.
self.assertTrue(line_entry.IsValid())
+ def test_args_constructor(self):
+ """SBLineEntry(filespec, line, column) constructor with default args."""
+ filespec = lldb.SBFileSpec(self.getSourcePath("test.cpp"), True)
+ line = 10
+ column = 30
+
+ line_entry = lldb.SBLineEntry(filespec, line, column)
+ self.assertEqual(line_entry.GetFileSpec(), filespec)
+ self.assertEqual(line_entry.GetLine(), line)
+ self.assertEqual(line_entry.GetColumn(), column)
+
+ line_entry = lldb.SBLineEntry(filespec, line)
+ self.assertEqual(line_entry.GetFileSpec(), filespec)
+ self.assertEqual(line_entry.GetLine(), line)
+ self.assertEqual(line_entry.GetColumn(), lldb.LLDB_INVALID_COLUMN_NUMBER)
+
+ line_entry = lldb.SBLineEntry(filespec)
+ self.assertEqual(line_entry.GetFileSpec(), filespec)
+ self.assertEqual(line_entry.GetLine(), lldb.LLDB_INVALID_LINE_NUMBER)
+ self.assertEqual(line_entry.GetColumn(), lldb.LLDB_INVALID_COLUMN_NUMBER)
+
def test_non_synthetic_line_entry_requires_line_number(self):
"""Test that non-synthetic line entries with addresses still require a line number to be valid."""
diff --git a/lldb/unittests/API/SBLineEntryTest.cpp b/lldb/unittests/API/SBLineEntryTest.cpp
index 518893b554bd1..17e62e142c6c4 100644
--- a/lldb/unittests/API/SBLineEntryTest.cpp
+++ b/lldb/unittests/API/SBLineEntryTest.cpp
@@ -21,6 +21,15 @@ TEST(SBLineEntryTest, SetLineAndColumn) {
const uint32_t line_no = line_entry.GetLine();
const uint32_t column_no = line_entry.GetColumn();
- EXPECT_EQ(line_no, line_no);
+ EXPECT_EQ(line_no, expected_line_no);
EXPECT_EQ(column_no, expected_column_no);
+
+ // Check args constructor.
+ lldb::SBFileSpec filespec("/some/random/path",
+ /*resolve=*/false);
+ auto cline_entry =
+ lldb::SBLineEntry(filespec, expected_line_no, expected_column_no);
+ EXPECT_EQ(cline_entry.GetFileSpec(), filespec);
+ EXPECT_EQ(cline_entry.GetLine(), expected_line_no);
+ EXPECT_EQ(cline_entry.GetColumn(), expected_column_no);
}
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 4acfcaf3204a7..0b20b2a8f7322 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -298,6 +298,13 @@ Makes programs 10x faster by doing Special New Thing.
return values that were actually in a different set. Both methods are now fixed
so that they are limited to the registers within the register set. Scripts
using these methods may have to be updated as a result.
+* New `SBTarget::FindSymbolContexts` and `SBModule::FindSymbolContexts`
+ return an `SBSymbolContextList` for every match of a given source location.
+* A new `SBLineEntry(SBFileSpec, line, column)` constructor lets
+ scripts build the location argument directly.
+* `SBLineEntry::GetLine()` and `SBLineEntry::GetColumn()` now return
+ `LLDB_INVALID_LINE_NUMBER` / `LLDB_INVALID_COLUMN_NUMBER` when unset;
+ scripts checking `entry.GetLine() == 0` should use `entry.IsValid()`.
#### Windows
More information about the lldb-commits
mailing list