[Lldb-commits] [lldb] [lldb][Expression] Add API to set/get language-specific expression options (PR #179208)

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Mon Feb 2 04:08:12 PST 2026


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 <michaelbuch12 at gmail.com>
Date: Mon, 2 Feb 2026 10:41:14 +0000
Subject: [PATCH 1/3] [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 <michaelbuch12 at gmail.com>
Date: Mon, 2 Feb 2026 11:25:33 +0000
Subject: [PATCH 2/3] 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 <michaelbuch12 at gmail.com>
Date: Mon, 2 Feb 2026 12:08:01 +0000
Subject: [PATCH 3/3] 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>
 



More information about the lldb-commits mailing list