https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/177279
>From 215acba81e2d88a0b03ab82928d5c707c846e612 Mon Sep 17 00:00:00 2001 From: Adrian Prantl <[email protected]> Date: Wed, 21 Jan 2026 16:06:00 -0800 Subject: [PATCH] [LLDB] Add a setting to simulate variables with missing locations Writing testcases for error handling that depends on specific DWARF is very difficult and the resulting tests tend not to be very portable. This patch adds a new setting to inject an error into variable materialization, thus making it possible to write very simple source code based tests for error handling instead. This is primarily motivated by the Swift language plugin, but functionality is generic and should be useful for other languages as well. --- lldb/include/lldb/Core/ModuleList.h | 14 +++++--- lldb/source/Core/CoreProperties.td | 10 ++++++ lldb/source/Core/ModuleList.cpp | 33 ++++++++++++++++++- lldb/source/Symbol/Variable.cpp | 13 ++++++-- .../diagnostics/TestExprDiagnostics.py | 18 ++++++++++ 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 1c023031b4c1b..4d506746d1b66 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -88,14 +88,20 @@ class ModuleListProperties : public Properties { uint64_t GetLLDBIndexCacheExpirationDays(); FileSpec GetLLDBIndexCachePath() const; bool SetLLDBIndexCachePath(const FileSpec &path); - - bool GetLoadSymbolOnDemand(); - + bool GetLoadSymbolOnDemand() const; lldb::SymbolDownload GetSymbolAutoDownload() const; - PathMappingList GetSymlinkMappings() const; }; +#ifndef NDEBUG +/// Global properties used in the LLDB testsuite. +struct TestingProperties : public Properties { + TestingProperties(); + bool GetInjectVarLocListError() const; + static TestingProperties &GetGlobalTestingProperties(); +}; +#endif + /// \class ModuleList ModuleList.h "lldb/Core/ModuleList.h" /// A collection class for Module objects. /// diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index 99bb5a3fc6f73..fafcb3b66e102 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -48,6 +48,16 @@ let Definition = "modulelist" in { Desc<"Enable on demand symbol loading in LLDB. LLDB will load debug info on demand for each module based on various conditions (e.g. matched breakpoint, resolved stack frame addresses and matched global variables/function symbols in symbol table) to improve performance. Please refer to docs/use/ondemand.rst for details.">; } +#ifndef NDEBUG +let Definition = "testing" in { + def InjectVarLocListError + : Property<"inject-variable-location-error", "Boolean">, + Global, + DefaultFalse, + Desc<"Used for testing LLDB only. Hide locations of local variables.">; +} +#endif + let Definition = "debugger" in { def AutoConfirm: Property<"auto-confirm", "Boolean">, Global, diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index f73f1541b7428..73f4487045e36 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -76,6 +76,16 @@ enum { #include "CorePropertiesEnum.inc" }; +#ifndef NDEBUG +#define LLDB_PROPERTIES_testing +#include "CoreProperties.inc" + +enum { +#define LLDB_PROPERTIES_testing +#include "CorePropertiesEnum.inc" +}; +#endif + } // namespace ModuleListProperties::ModuleListProperties() { @@ -95,9 +105,21 @@ ModuleListProperties::ModuleListProperties() { llvm::sys::path::append(path, "IndexCache"); lldbassert(SetLLDBIndexCachePath(FileSpec(path))); } +} +#ifndef NDEBUG +TestingProperties::TestingProperties() { + m_collection_sp = std::make_shared<OptionValueProperties>("testing"); + m_collection_sp->Initialize(g_testing_properties); } +bool TestingProperties::GetInjectVarLocListError() const { + const uint32_t idx = ePropertyInjectVarLocListError; + return GetPropertyAtIndexAs<bool>( + idx, g_testing_properties[idx].default_uint_value != 0); +} +#endif + bool ModuleListProperties::GetEnableExternalLookup() const { const uint32_t idx = ePropertyEnableExternalLookup; return GetPropertyAtIndexAs<bool>( @@ -186,7 +208,7 @@ PathMappingList ModuleListProperties::GetSymlinkMappings() const { return m_symlink_paths; } -bool ModuleListProperties::GetLoadSymbolOnDemand() { +bool ModuleListProperties::GetLoadSymbolOnDemand() const { const uint32_t idx = ePropertyLoadSymbolOnDemand; return GetPropertyAtIndexAs<bool>( idx, g_modulelist_properties[idx].default_uint_value != 0); @@ -999,6 +1021,9 @@ class SharedModuleList { struct SharedModuleListInfo { SharedModuleList module_list; ModuleListProperties module_list_properties; +#ifndef NDEBUG + TestingProperties testing_properties; +#endif }; } static SharedModuleListInfo &GetSharedModuleListInfo() @@ -1023,6 +1048,12 @@ ModuleListProperties &ModuleList::GetGlobalModuleListProperties() { return GetSharedModuleListInfo().module_list_properties; } +#ifndef NDEBUG +TestingProperties &TestingProperties::GetGlobalTestingProperties() { + return GetSharedModuleListInfo().testing_properties; +} +#endif + bool ModuleList::ModuleIsInCache(const Module *module_ptr) { if (module_ptr) { SharedModuleList &shared_module_list = GetSharedModuleList(); diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index af32e0e958e51..60eac2eee8546 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -47,9 +47,16 @@ Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled, : UserID(uid), m_name(name), m_mangled(ConstString(mangled)), m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), m_scope_range(scope_range), - m_declaration(decl_ptr), m_location_list(location_list), m_external(external), - m_artificial(artificial), m_loc_is_const_data(location_is_constant_data), - m_static_member(static_member) {} + m_declaration(decl_ptr), m_location_list(location_list), + m_external(external), m_artificial(artificial), + m_loc_is_const_data(location_is_constant_data), + m_static_member(static_member) { +#ifndef NDEBUG + if (TestingProperties::GetGlobalTestingProperties() + .GetInjectVarLocListError()) + m_location_list.Clear(); +#endif +} Variable::~Variable() = default; diff --git a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py index 759b620105c4e..1f87a6918bb21 100644 --- a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py +++ b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py @@ -272,3 +272,21 @@ def check_error(diags): self.assertEqual(err_ty.GetIntegerValue(), lldb.eErrorTypeExpression) diags = data.GetValueForKey("errors").GetItemAtIndex(0) check_error(diags) + + def test_no_location(self): + """Test the error reporting for missing locations""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "// Break here", self.main_source_spec + ) + self.ci.HandleCommand( + "settings set testing.inject-variable-location-error true", self.res + ) + if not self.res.Succeeded(): + # This test needs assertions. + return + frame = thread.GetFrameAtIndex(0) + value = frame.EvaluateExpression("f") + error = value.GetError() + self.assertIn("variable not available", str(error)) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
