https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/179208
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 >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] [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("")); +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
