[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
Tue Feb 3 03:23:07 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/9] [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/9] 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/9] 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 <michaelbuch12 at gmail.com>
Date: Mon, 2 Feb 2026 12:11:49 +0000
Subject: [PATCH 4/9] 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 <michaelbuch12 at gmail.com>
Date: Tue, 3 Feb 2026 07:59:51 +0000
Subject: [PATCH 5/9] 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 <michaelbuch12 at gmail.com>
Date: Tue, 3 Feb 2026 10:57:11 +0000
Subject: [PATCH 6/9] 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 <michaelbuch12 at gmail.com>
Date: Tue, 3 Feb 2026 10:58:07 +0000
Subject: [PATCH 7/9] 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 <michaelbuch12 at gmail.com>
Date: Tue, 3 Feb 2026 11:10:40 +0000
Subject: [PATCH 8/9] 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."));
}
>From 6a3032ae767f591844df7a6467a30ec1d7d7319d Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 3 Feb 2026 11:22:54 +0000
Subject: [PATCH 9/9] fixup! fix test comment
---
lldb/test/API/commands/expression/options/TestExprOptions.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py
index ed4109b3e2f20..02f844b34cc2b 100644
--- a/lldb/test/API/commands/expression/options/TestExprOptions.py
+++ b/lldb/test/API/commands/expression/options/TestExprOptions.py
@@ -86,7 +86,7 @@ def test_expr_options_lang(self):
self.assertFalse(val.GetError().Success())
def test_expr_options_language_options(self):
- """Test SetLanguageOption/GetLanguageOption SBAPIs"""
+ """Test SetBooleanLanguageOption/GetBooleanLanguageOption SBAPIs"""
error = lldb.SBError()
options = lldb.SBExpressionOptions()
More information about the lldb-commits
mailing list