https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/179208
>From 4adc40f712e657c71c7ac42160b18e9bedddafb9 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 2 Feb 2026 10:41:14 +0000 Subject: [PATCH 1/8] [lldb][Expression] Add API to set/get language-specific expression options The motivation here is that we don't want to pollute the SBAPI with getters/setters for expression evaluation options that only apply to a single language. The ultimate goal would be to have plugins register additional options to the `expression` command when the plugin is loaded. This patch only provides the minimal `SBExpressionOptions` interface to set an option with an arbitrary name, which the language plugin knows how to interpret. The underlying options dictionary is an `StructuredData::Dictionary` so we can map strings to values of any type. But the SBAPI just exposes setting a boolean value. Future overloads of `SetLanguageOption` can provide setters for more types. The boolean setter/getter will be used for the C++-specific option being introduced in: https://github.com/llvm/llvm-project/pull/177926 --- .../interface/SBExpressionOptionsDocstrings.i | 6 +++ lldb/include/lldb/API/SBExpressionOptions.h | 5 +++ lldb/include/lldb/Target/Target.h | 42 ++++++++++++++++++- lldb/source/API/SBExpressionOptions.cpp | 12 ++++++ .../expression/options/TestExprOptions.py | 25 ++++++++++- lldb/unittests/Expression/ExpressionTest.cpp | 25 +++++++++++ 6 files changed, 112 insertions(+), 3 deletions(-) diff --git a/lldb/bindings/interface/SBExpressionOptionsDocstrings.i b/lldb/bindings/interface/SBExpressionOptionsDocstrings.i index 2bb562778db79..a6de6f034bd7a 100644 --- a/lldb/bindings/interface/SBExpressionOptionsDocstrings.i +++ b/lldb/bindings/interface/SBExpressionOptionsDocstrings.i @@ -61,3 +61,9 @@ %feature("docstring", "Sets whether to JIT an expression if it cannot be interpreted." ) lldb::SBExpressionOptions::SetAllowJIT; + +%feature("docstring", "Sets language-plugin specific boolean option for expression evaluation." +) lldb::SBExpressionOptions::SetLanguageOption; + +%feature("docstring", "Gets language-plugin specific boolean option for expression evaluation." +) lldb::SBExpressionOptions::GetLanguageOptionAsBoolean; diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index a9e929a4c0bd9..6f7bd53d6fa70 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -11,6 +11,7 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBLanguages.h" +#include "lldb/API/SBStructuredData.h" #include <vector> @@ -107,6 +108,10 @@ class LLDB_API SBExpressionOptions { // Sets whether we will JIT an expression if it cannot be interpreted void SetAllowJIT(bool allow); + bool GetLanguageOptionAsBoolean(const char *option_name) const; + + void SetLanguageOption(const char *option_name, bool value); + protected: lldb_private::EvaluateExpressionOptions *get() const; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 812a638910b3b..2583c14965e61 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -15,6 +15,7 @@ #include <string> #include <vector> +#include "lldb/API/SBStructuredData.h" #include "lldb/Breakpoint/BreakpointList.h" #include "lldb/Breakpoint/BreakpointName.h" #include "lldb/Breakpoint/WatchpointList.h" @@ -307,6 +308,8 @@ class TargetProperties : public Properties { class EvaluateExpressionOptions { public: + EvaluateExpressionOptions() : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) {} + // MSVC has a bug here that reports C4268: 'const' static/global data // initialized with compiler generated default constructor fills the object // with zeros. Confirmed that MSVC is *not* zero-initializing, it's just a @@ -323,8 +326,6 @@ class EvaluateExpressionOptions { static constexpr ExecutionPolicy default_execution_policy = eExecutionPolicyOnlyWhenNeeded; - EvaluateExpressionOptions() = default; - ExecutionPolicy GetExecutionPolicy() const { return m_execution_policy; } void SetExecutionPolicy(ExecutionPolicy policy = eExecutionPolicyAlways) { @@ -481,7 +482,40 @@ class EvaluateExpressionOptions { void SetIsForUtilityExpr(bool b) { m_running_utility_expression = b; } + /// Set language-plugin specific option called \c option_name to + /// the specified boolean \c value. + void SetLanguageOption(llvm::StringRef option_name, bool value) { + if (option_name.empty()) + return; + + GetLanguageOptions().AddBooleanItem(option_name, value); + } + + /// Get the language-plugin specific boolean option called \c option_name. + /// + /// If the option doesn't exist or is not a boolean option, returns false. + /// Otherwise returns the boolean value of the option. + bool GetLanguageOptionAsBoolean(llvm::StringRef option_name) const { + bool result; + if (!GetLanguageOptions().GetValueForKeyAsBoolean(option_name, result)) + return false; + + return result; + } + private: + const StructuredData::Dictionary &GetLanguageOptions() const { + assert (m_language_options_sp); + + return *m_language_options_sp; + } + + StructuredData::Dictionary &GetLanguageOptions() { + assert (m_language_options_sp); + + return *m_language_options_sp; + } + ExecutionPolicy m_execution_policy = default_execution_policy; SourceLanguage m_language; std::string m_prefix; @@ -514,6 +548,10 @@ class EvaluateExpressionOptions { mutable std::string m_pound_line_file; mutable uint32_t m_pound_line_line = 0; + /// Dictionary mapping names of language-plugin specific options + /// to values. + StructuredData::DictionarySP m_language_options_sp = nullptr; + /// During expression evaluation, any SymbolContext in this list will be /// used for symbol/function lookup before any other context (except for /// the module corresponding to the current frame). diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index 15ed403eaaea1..e28c7ebfd0133 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -256,6 +256,18 @@ void SBExpressionOptions::SetAllowJIT(bool allow) { : eExecutionPolicyNever); } +bool SBExpressionOptions::GetLanguageOptionAsBoolean(const char *option_name) const { + LLDB_INSTRUMENT_VA(this, option_name); + + return m_opaque_up->GetLanguageOptionAsBoolean(option_name); +} + +void SBExpressionOptions::SetLanguageOption(const char *option_name, bool value) { + LLDB_INSTRUMENT_VA(this, option_name, value); + + m_opaque_up->SetLanguageOption(option_name, value); + } + EvaluateExpressionOptions *SBExpressionOptions::get() const { return m_opaque_up.get(); } diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py index 01899f3b97cf4..96bb4742a1a10 100644 --- a/lldb/test/API/commands/expression/options/TestExprOptions.py +++ b/lldb/test/API/commands/expression/options/TestExprOptions.py @@ -7,7 +7,6 @@ Test expression command options. """ - import lldb import lldbsuite.test.lldbutil as lldbutil from lldbsuite.test.decorators import * @@ -85,3 +84,27 @@ def test_expr_options_lang(self): val = frame.EvaluateExpression("id == 0", options) self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success()) + + def test_expr_options_language_options(self): + """Test SetLanguageOption/GetLanguageOption SBAPIs""" + + options = lldb.SBExpressionOptions() + self.assertFalse(options.GetLanguageOptionAsBoolean("foo")) + self.assertFalse(options.GetLanguageOptionAsBoolean("bar")) + + options.SetLanguageOption("foo", True) + options.SetLanguageOption("bar", True) + self.assertTrue(options.GetLanguageOptionAsBoolean("foo")) + self.assertTrue(options.GetLanguageOptionAsBoolean("bar")) + + options.SetLanguageOption("foo", False) + options.SetLanguageOption("bar", False) + self.assertFalse(options.GetLanguageOptionAsBoolean("foo")) + self.assertFalse(options.GetLanguageOptionAsBoolean("bar")) + + self.assertFalse(options.GetLanguageOptionAsBoolean("")) + options.SetLanguageOption("", True) + self.assertFalse(options.GetLanguageOptionAsBoolean("")) + + options.SetLanguageOption(None, True) + self.assertFalse(options.GetLanguageOptionAsBoolean(None)) diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp index ceb567c28ab99..4201516dfc820 100644 --- a/lldb/unittests/Expression/ExpressionTest.cpp +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -10,6 +10,7 @@ #include "gtest/gtest.h" #include "TestingSupport/TestUtilities.h" +#include "lldb/Target/Target.h" #include "lldb/Expression/Expression.h" #include "llvm/Testing/Support/Error.h" @@ -127,3 +128,27 @@ TEST_P(ExpressionTestFixture, FunctionCallLabel) { INSTANTIATE_TEST_SUITE_P(FunctionCallLabelTest, ExpressionTestFixture, testing::ValuesIn(g_label_test_cases)); + +TEST(ExpressionTests, ExpressionOptions_Basic) { + EvaluateExpressionOptions options; + + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("foo")); + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("bar")); + + options.SetLanguageOption("foo", true); + options.SetLanguageOption("bar", true); + + ASSERT_TRUE(options.GetLanguageOptionAsBoolean("foo")); + ASSERT_TRUE(options.GetLanguageOptionAsBoolean("bar")); + + options.SetLanguageOption("foo", false); + options.SetLanguageOption("bar", false); + + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("foo")); + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("bar")); + + // Empty option names not allowed. + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("")); + options.SetLanguageOption("", true); + ASSERT_FALSE(options.GetLanguageOptionAsBoolean("")); +} >From f1d8205d7923773f343e54105c7f60300851e123 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 2 Feb 2026 11:25:33 +0000 Subject: [PATCH 2/8] fixup! clang-format --- lldb/include/lldb/API/SBExpressionOptions.h | 2 +- lldb/include/lldb/Target/Target.h | 7 ++++--- lldb/source/API/SBExpressionOptions.cpp | 8 +++++--- lldb/unittests/Expression/ExpressionTest.cpp | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index 6f7bd53d6fa70..f0a37589fabe4 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -109,7 +109,7 @@ class LLDB_API SBExpressionOptions { void SetAllowJIT(bool allow); bool GetLanguageOptionAsBoolean(const char *option_name) const; - + void SetLanguageOption(const char *option_name, bool value); protected: diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 2583c14965e61..67581e745c3d4 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -308,7 +308,8 @@ class TargetProperties : public Properties { class EvaluateExpressionOptions { public: - EvaluateExpressionOptions() : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) {} + EvaluateExpressionOptions() + : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) {} // MSVC has a bug here that reports C4268: 'const' static/global data // initialized with compiler generated default constructor fills the object @@ -505,13 +506,13 @@ class EvaluateExpressionOptions { private: const StructuredData::Dictionary &GetLanguageOptions() const { - assert (m_language_options_sp); + assert(m_language_options_sp); return *m_language_options_sp; } StructuredData::Dictionary &GetLanguageOptions() { - assert (m_language_options_sp); + assert(m_language_options_sp); return *m_language_options_sp; } diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index e28c7ebfd0133..98a55733fbc3c 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -256,17 +256,19 @@ void SBExpressionOptions::SetAllowJIT(bool allow) { : eExecutionPolicyNever); } -bool SBExpressionOptions::GetLanguageOptionAsBoolean(const char *option_name) const { +bool SBExpressionOptions::GetLanguageOptionAsBoolean( + const char *option_name) const { LLDB_INSTRUMENT_VA(this, option_name); return m_opaque_up->GetLanguageOptionAsBoolean(option_name); } -void SBExpressionOptions::SetLanguageOption(const char *option_name, bool value) { +void SBExpressionOptions::SetLanguageOption(const char *option_name, + bool value) { LLDB_INSTRUMENT_VA(this, option_name, value); m_opaque_up->SetLanguageOption(option_name, value); - } +} EvaluateExpressionOptions *SBExpressionOptions::get() const { return m_opaque_up.get(); diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp index 4201516dfc820..8bf8b20bc5203 100644 --- a/lldb/unittests/Expression/ExpressionTest.cpp +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -10,8 +10,8 @@ #include "gtest/gtest.h" #include "TestingSupport/TestUtilities.h" -#include "lldb/Target/Target.h" #include "lldb/Expression/Expression.h" +#include "lldb/Target/Target.h" #include "llvm/Testing/Support/Error.h" using namespace lldb_private; >From e468faab2c9fdad045e7b479a7086bc9b39eab5e Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 2 Feb 2026 12:08:01 +0000 Subject: [PATCH 3/8] fixup! remove redundant include --- lldb/include/lldb/API/SBExpressionOptions.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index f0a37589fabe4..8ef4204c302c1 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -11,7 +11,6 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBLanguages.h" -#include "lldb/API/SBStructuredData.h" #include <vector> >From a84c45136bef59abebf2b6b88f772adb5ab7f50e Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 2 Feb 2026 12:11:49 +0000 Subject: [PATCH 4/8] fixup! include correct header --- lldb/include/lldb/Target/Target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 67581e745c3d4..0d71a70dac2fa 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -15,7 +15,6 @@ #include <string> #include <vector> -#include "lldb/API/SBStructuredData.h" #include "lldb/Breakpoint/BreakpointList.h" #include "lldb/Breakpoint/BreakpointName.h" #include "lldb/Breakpoint/WatchpointList.h" @@ -39,6 +38,7 @@ #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/RealpathPrefixes.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-public.h" #include "llvm/ADT/StringRef.h" >From 2deb9036303f8e78036c3e8c10b8106138f61147 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 3 Feb 2026 07:59:51 +0000 Subject: [PATCH 5/8] fixup! move definition to Target.cpp --- lldb/include/lldb/Target/Target.h | 27 ++++----------------------- lldb/source/Target/Target.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 0d71a70dac2fa..380972b706af9 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -485,37 +485,18 @@ class EvaluateExpressionOptions { /// Set language-plugin specific option called \c option_name to /// the specified boolean \c value. - void SetLanguageOption(llvm::StringRef option_name, bool value) { - if (option_name.empty()) - return; - - GetLanguageOptions().AddBooleanItem(option_name, value); - } + void SetLanguageOption(llvm::StringRef option_name, bool value); /// Get the language-plugin specific boolean option called \c option_name. /// /// If the option doesn't exist or is not a boolean option, returns false. /// Otherwise returns the boolean value of the option. - bool GetLanguageOptionAsBoolean(llvm::StringRef option_name) const { - bool result; - if (!GetLanguageOptions().GetValueForKeyAsBoolean(option_name, result)) - return false; - - return result; - } + bool GetLanguageOptionAsBoolean(llvm::StringRef option_name) const; private: - const StructuredData::Dictionary &GetLanguageOptions() const { - assert(m_language_options_sp); + const StructuredData::Dictionary &GetLanguageOptions() const; - return *m_language_options_sp; - } - - StructuredData::Dictionary &GetLanguageOptions() { - assert(m_language_options_sp); - - return *m_language_options_sp; - } + StructuredData::Dictionary &GetLanguageOptions(); ExecutionPolicy m_execution_policy = default_execution_policy; SourceLanguage m_language; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index f3e058c6cbc9b..658078d9def6f 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -5357,3 +5357,33 @@ void Target::NotifyBreakpointChanged( if (EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) BroadcastEvent(Target::eBroadcastBitBreakpointChanged, breakpoint_data_sp); } + +void EvaluateExpressionOptions::SetLanguageOption(llvm::StringRef option_name, + bool value) { + if (option_name.empty()) + return; + + GetLanguageOptions().AddBooleanItem(option_name, value); +} + +bool EvaluateExpressionOptions::GetLanguageOptionAsBoolean( + llvm::StringRef option_name) const { + bool result; + if (!GetLanguageOptions().GetValueForKeyAsBoolean(option_name, result)) + return false; + + return result; +} + +const StructuredData::Dictionary & +EvaluateExpressionOptions::GetLanguageOptions() const { + assert(m_language_options_sp); + + return *m_language_options_sp; +} + +StructuredData::Dictionary &EvaluateExpressionOptions::GetLanguageOptions() { + assert(m_language_options_sp); + + return *m_language_options_sp; +} >From e1591e342a5f0893ce158e45a805bfebc0a14249 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 3 Feb 2026 10:57:11 +0000 Subject: [PATCH 6/8] fixup! rename APIs; add SBError to APIs --- .../interface/SBExpressionOptionsDocstrings.i | 4 +- lldb/include/lldb/API/SBExpressionOptions.h | 4 +- lldb/include/lldb/Target/Target.h | 5 +- lldb/source/API/SBExpressionOptions.cpp | 29 +++++++++--- lldb/source/Target/Target.cpp | 22 ++++++--- .../expression/options/TestExprOptions.py | 47 ++++++++++++------- 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/lldb/bindings/interface/SBExpressionOptionsDocstrings.i b/lldb/bindings/interface/SBExpressionOptionsDocstrings.i index a6de6f034bd7a..ae897a6aa5bcd 100644 --- a/lldb/bindings/interface/SBExpressionOptionsDocstrings.i +++ b/lldb/bindings/interface/SBExpressionOptionsDocstrings.i @@ -63,7 +63,7 @@ ) lldb::SBExpressionOptions::SetAllowJIT; %feature("docstring", "Sets language-plugin specific boolean option for expression evaluation." -) lldb::SBExpressionOptions::SetLanguageOption; +) lldb::SBExpressionOptions::SetBooleanLanguageOption; %feature("docstring", "Gets language-plugin specific boolean option for expression evaluation." -) lldb::SBExpressionOptions::GetLanguageOptionAsBoolean; +) lldb::SBExpressionOptions::GetBooleanLanguageOption; diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index 8ef4204c302c1..edfdbb5aaf62f 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -107,9 +107,9 @@ class LLDB_API SBExpressionOptions { // Sets whether we will JIT an expression if it cannot be interpreted void SetAllowJIT(bool allow); - bool GetLanguageOptionAsBoolean(const char *option_name) const; + bool GetBooleanLanguageOption(const char *option_name, SBError &error) const; - void SetLanguageOption(const char *option_name, bool value); + SBError SetBooleanLanguageOption(const char *option_name, bool value); protected: lldb_private::EvaluateExpressionOptions *get() const; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 380972b706af9..a79d0f1b6113e 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -485,13 +485,14 @@ class EvaluateExpressionOptions { /// Set language-plugin specific option called \c option_name to /// the specified boolean \c value. - void SetLanguageOption(llvm::StringRef option_name, bool value); + llvm::Error SetBooleanLanguageOption(llvm::StringRef option_name, bool value); /// Get the language-plugin specific boolean option called \c option_name. /// /// If the option doesn't exist or is not a boolean option, returns false. /// Otherwise returns the boolean value of the option. - bool GetLanguageOptionAsBoolean(llvm::StringRef option_name) const; + llvm::Expected<bool> + GetBooleanLanguageOption(llvm::StringRef option_name) const; private: const StructuredData::Dictionary &GetLanguageOptions() const; diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index 98a55733fbc3c..908f69a4cba3f 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -8,6 +8,7 @@ #include "lldb/API/SBExpressionOptions.h" #include "Utils.h" +#include "lldb/API/SBError.h" #include "lldb/API/SBStream.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Instrumentation.h" @@ -256,18 +257,32 @@ void SBExpressionOptions::SetAllowJIT(bool allow) { : eExecutionPolicyNever); } -bool SBExpressionOptions::GetLanguageOptionAsBoolean( - const char *option_name) const { - LLDB_INSTRUMENT_VA(this, option_name); +bool SBExpressionOptions::GetBooleanLanguageOption(const char *option_name, + SBError &error) const { + LLDB_INSTRUMENT_VA(this, option_name, error); - return m_opaque_up->GetLanguageOptionAsBoolean(option_name); + error.Clear(); + + auto value_or_err = m_opaque_up->GetBooleanLanguageOption(option_name); + if (!value_or_err) { + error.SetErrorString(llvm::toString(value_or_err.takeError()).c_str()); + return false; + } + + return *value_or_err; } -void SBExpressionOptions::SetLanguageOption(const char *option_name, - bool value) { +SBError SBExpressionOptions::SetBooleanLanguageOption(const char *option_name, + bool value) { LLDB_INSTRUMENT_VA(this, option_name, value); - m_opaque_up->SetLanguageOption(option_name, value); + SBError error; + + if (llvm::Error err = + m_opaque_up->SetBooleanLanguageOption(option_name, value)) + error.SetErrorString(llvm::toString(std::move(err)).c_str()); + + return error; } EvaluateExpressionOptions *SBExpressionOptions::get() const { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 658078d9def6f..796318d9cb7da 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -70,6 +70,7 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SetVector.h" +#include "llvm/Support/ErrorExtras.h" #include "llvm/Support/ThreadPool.h" #include <memory> @@ -5358,19 +5359,28 @@ void Target::NotifyBreakpointChanged( BroadcastEvent(Target::eBroadcastBitBreakpointChanged, breakpoint_data_sp); } -void EvaluateExpressionOptions::SetLanguageOption(llvm::StringRef option_name, - bool value) { +llvm::Error +EvaluateExpressionOptions::SetBooleanLanguageOption(llvm::StringRef option_name, + bool value) { if (option_name.empty()) - return; + return llvm::createStringError("Can't set an option with an empty name."); GetLanguageOptions().AddBooleanItem(option_name, value); + + return llvm::Error::success(); } -bool EvaluateExpressionOptions::GetLanguageOptionAsBoolean( +llvm::Expected<bool> EvaluateExpressionOptions::GetBooleanLanguageOption( llvm::StringRef option_name) const { + const StructuredData::Dictionary &opts = GetLanguageOptions(); + + if (!opts.HasKey(option_name)) + return llvm::createStringErrorV("Option {0} does not exist.", option_name); + bool result; - if (!GetLanguageOptions().GetValueForKeyAsBoolean(option_name, result)) - return false; + if (!opts.GetValueForKeyAsBoolean(option_name, result)) + return llvm::createStringErrorV("Failed to get option {0} as boolean.", + option_name); return result; } diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py index 96bb4742a1a10..c2c37152e64ae 100644 --- a/lldb/test/API/commands/expression/options/TestExprOptions.py +++ b/lldb/test/API/commands/expression/options/TestExprOptions.py @@ -88,23 +88,34 @@ def test_expr_options_lang(self): def test_expr_options_language_options(self): """Test SetLanguageOption/GetLanguageOption SBAPIs""" + error = lldb.SBError() options = lldb.SBExpressionOptions() - self.assertFalse(options.GetLanguageOptionAsBoolean("foo")) - self.assertFalse(options.GetLanguageOptionAsBoolean("bar")) - options.SetLanguageOption("foo", True) - options.SetLanguageOption("bar", True) - self.assertTrue(options.GetLanguageOptionAsBoolean("foo")) - self.assertTrue(options.GetLanguageOptionAsBoolean("bar")) - - options.SetLanguageOption("foo", False) - options.SetLanguageOption("bar", False) - self.assertFalse(options.GetLanguageOptionAsBoolean("foo")) - self.assertFalse(options.GetLanguageOptionAsBoolean("bar")) - - self.assertFalse(options.GetLanguageOptionAsBoolean("")) - options.SetLanguageOption("", True) - self.assertFalse(options.GetLanguageOptionAsBoolean("")) - - options.SetLanguageOption(None, True) - self.assertFalse(options.GetLanguageOptionAsBoolean(None)) + self.assertFalse(options.GetBooleanLanguageOption("foo", error)) + self.assertTrue(error.Fail()) + self.assertFalse(options.GetBooleanLanguageOption("bar", error)) + self.assertTrue(error.Fail()) + + self.assertTrue(options.SetBooleanLanguageOption("foo", True).Success()) + self.assertTrue(options.SetBooleanLanguageOption("bar", True).Success()) + self.assertTrue(options.GetBooleanLanguageOption("foo", error)) + self.assertTrue(error.Success()) + self.assertTrue(options.GetBooleanLanguageOption("bar", error)) + self.assertTrue(error.Success()) + + self.assertTrue(options.SetBooleanLanguageOption("foo", False).Success()) + self.assertTrue(options.SetBooleanLanguageOption("bar", False).Success()) + self.assertFalse(options.GetBooleanLanguageOption("foo", error)) + self.assertTrue(error.Success()) + self.assertFalse(options.GetBooleanLanguageOption("bar", error)) + self.assertTrue(error.Success()) + + self.assertFalse(options.GetBooleanLanguageOption("", error)) + self.assertTrue(error.Fail()) + self.assertFalse(options.SetBooleanLanguageOption("", True).Fail()) + self.assertFalse(options.GetBooleanLanguageOption("", error)) + self.assertTrue(error.Fail()) + + self.assertFalse(options.SetBooleanLanguageOption(None, True).Fail()) + self.assertFalse(options.GetBooleanLanguageOption(None, error)) + self.assertTrue(error.Fail()) >From 1a0276b9e3670dc290041f1e0a3ea3b529b0c01b Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 3 Feb 2026 10:58:07 +0000 Subject: [PATCH 7/8] fixup! rename APIs; add SBError to APIs --- lldb/test/API/commands/expression/options/TestExprOptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py index c2c37152e64ae..ed4109b3e2f20 100644 --- a/lldb/test/API/commands/expression/options/TestExprOptions.py +++ b/lldb/test/API/commands/expression/options/TestExprOptions.py @@ -112,10 +112,10 @@ def test_expr_options_language_options(self): self.assertFalse(options.GetBooleanLanguageOption("", error)) self.assertTrue(error.Fail()) - self.assertFalse(options.SetBooleanLanguageOption("", True).Fail()) + self.assertTrue(options.SetBooleanLanguageOption("", True).Fail()) self.assertFalse(options.GetBooleanLanguageOption("", error)) self.assertTrue(error.Fail()) - self.assertFalse(options.SetBooleanLanguageOption(None, True).Fail()) + self.assertTrue(options.SetBooleanLanguageOption(None, True).Fail()) self.assertFalse(options.GetBooleanLanguageOption(None, error)) self.assertTrue(error.Fail()) >From dc3a7efb50fb309f819c6820384578f2e63d7ce1 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Tue, 3 Feb 2026 11:10:40 +0000 Subject: [PATCH 8/8] fixup! add unit-tests --- lldb/source/Target/Target.cpp | 5 +- lldb/unittests/Expression/ExpressionTest.cpp | 48 +++++++++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 796318d9cb7da..6b6dfa4aebe2b 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -5375,11 +5375,12 @@ llvm::Expected<bool> EvaluateExpressionOptions::GetBooleanLanguageOption( const StructuredData::Dictionary &opts = GetLanguageOptions(); if (!opts.HasKey(option_name)) - return llvm::createStringErrorV("Option {0} does not exist.", option_name); + return llvm::createStringErrorV("Option '{0}' does not exist.", + option_name); bool result; if (!opts.GetValueForKeyAsBoolean(option_name, result)) - return llvm::createStringErrorV("Failed to get option {0} as boolean.", + return llvm::createStringErrorV("Failed to get option '{0}' as boolean.", option_name); return result; diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp index 8bf8b20bc5203..19647c162fa5a 100644 --- a/lldb/unittests/Expression/ExpressionTest.cpp +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -132,23 +132,37 @@ INSTANTIATE_TEST_SUITE_P(FunctionCallLabelTest, ExpressionTestFixture, TEST(ExpressionTests, ExpressionOptions_Basic) { EvaluateExpressionOptions options; - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("foo")); - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("bar")); - - options.SetLanguageOption("foo", true); - options.SetLanguageOption("bar", true); - - ASSERT_TRUE(options.GetLanguageOptionAsBoolean("foo")); - ASSERT_TRUE(options.GetLanguageOptionAsBoolean("bar")); - - options.SetLanguageOption("foo", false); - options.SetLanguageOption("bar", false); - - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("foo")); - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("bar")); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("foo"), + llvm::FailedWithMessage("Option 'foo' does not exist.")); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("bar"), + llvm::FailedWithMessage("Option 'bar' does not exist.")); + + EXPECT_THAT_ERROR(options.SetBooleanLanguageOption("foo", true), + llvm::Succeeded()); + EXPECT_THAT_ERROR(options.SetBooleanLanguageOption("bar", false), + llvm::Succeeded()); + + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("foo"), + llvm::HasValue(true)); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("bar"), + llvm::HasValue(false)); + + EXPECT_THAT_ERROR(options.SetBooleanLanguageOption("foo", false), + llvm::Succeeded()); + EXPECT_THAT_ERROR(options.SetBooleanLanguageOption("bar", true), + llvm::Succeeded()); + + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("foo"), + llvm::HasValue(false)); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption("bar"), + llvm::HasValue(true)); // Empty option names not allowed. - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("")); - options.SetLanguageOption("", true); - ASSERT_FALSE(options.GetLanguageOptionAsBoolean("")); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption(""), + llvm::FailedWithMessage("Option '' does not exist.")); + EXPECT_THAT_ERROR( + options.SetBooleanLanguageOption("", true), + llvm::FailedWithMessage("Can't set an option with an empty name.")); + EXPECT_THAT_EXPECTED(options.GetBooleanLanguageOption(""), + llvm::FailedWithMessage("Option '' does not exist.")); } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
