https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/158759
>From 9744d606c8ddc03aeba105c89647af4c009dac28 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <ism...@bennani.ma> Date: Mon, 15 Sep 2025 18:04:48 -0700 Subject: [PATCH] [lldb/API] Mark SBValue with error as invalid This patch fixes the return value of `SBValue::IsValid` if `GetError` returns a failing `SBError`. That alignes better the expectation that an `SBValue` is invalid if it has an error. Signed-off-by: Med Ismail Bennani <ism...@bennani.ma> --- lldb/source/API/SBValue.cpp | 3 ++- .../expression/call-throws/TestCallThatThrows.py | 11 +++++++---- .../expression/context-object/TestContextObject.py | 10 +++++----- .../test/API/commands/expression/fixits/TestFixIts.py | 2 +- .../commands/expression/options/TestExprOptions.py | 4 ++-- .../expression/scoped_enums/TestScopedEnumType.py | 4 ++-- .../expression/timeout/TestCallWithTimeout.py | 2 +- .../python_api/sbvalue_is_valid/TestSBValueIsValid.py | 3 +++ lldb/test/API/python_api/sbvalue_is_valid/main.cpp | 7 +++++++ 9 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 lldb/test/API/python_api/sbvalue_is_valid/TestSBValueIsValid.py create mode 100644 lldb/test/API/python_api/sbvalue_is_valid/main.cpp diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index e300ecee3f8ac..77cc7d1681829 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -97,7 +97,8 @@ class ValueImpl { // they depend on. So I have no good way to make that check without // tracking that in all the ValueObject subclasses. TargetSP target_sp = m_valobj_sp->GetTargetSP(); - return target_sp && target_sp->IsValid(); + return target_sp && target_sp->IsValid() && + m_valobj_sp->GetError().Success(); } } diff --git a/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py b/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py index 0090513864cd7..4d5e5a36eb72a 100644 --- a/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py +++ b/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py @@ -45,7 +45,7 @@ def call_function(self): self.orig_frame_pc = frame.GetPC() value = frame.EvaluateExpression("[my_class callMeIThrow]", options) - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) self.check_after_call() @@ -61,7 +61,8 @@ def call_function(self): value = frame.EvaluateExpression("[my_class callMeIThrow]", options) - self.assertTrue(value.IsValid() and not value.GetError().Success()) + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) self.check_after_call() # Now set the ObjC language breakpoint and make sure that doesn't @@ -76,7 +77,8 @@ def call_function(self): value = frame.EvaluateExpression("[my_class callMeIThrow]", options) - self.assertTrue(value.IsValid() and not value.GetError().Success()) + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) self.check_after_call() # Now turn off exception trapping, and call a function that catches the exceptions, @@ -95,5 +97,6 @@ def call_function(self): options.SetUnwindOnError(False) value = frame.EvaluateExpression("[my_class callMeIThrow]", options) - self.assertTrue(value.IsValid() and not value.GetError().Success()) + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) self.check_after_call() diff --git a/lldb/test/API/commands/expression/context-object/TestContextObject.py b/lldb/test/API/commands/expression/context-object/TestContextObject.py index 1ed629a42c1ee..f3b2c3a503592 100644 --- a/lldb/test/API/commands/expression/context-object/TestContextObject.py +++ b/lldb/test/API/commands/expression/context-object/TestContextObject.py @@ -69,7 +69,7 @@ def test_context_object(self): # Test an expression evaluation value = obj_val.EvaluateExpression("1") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # @@ -81,7 +81,7 @@ def test_context_object(self): # Test an expression evaluation value = obj_val.EvaluateExpression("1") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # Test retrieveing of an element's field @@ -99,7 +99,7 @@ def test_context_object(self): # Test an expression evaluation value = obj_val.EvaluateExpression("1") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # Test retrieveing of a dereferenced object's field @@ -117,7 +117,7 @@ def test_context_object(self): # Test an expression evaluation value = obj_val.EvaluateExpression("1") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # @@ -129,7 +129,7 @@ def test_context_object(self): # Test an expression evaluation value = obj_val.EvaluateExpression("1") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # Test retrieveing of a dereferenced object's field diff --git a/lldb/test/API/commands/expression/fixits/TestFixIts.py b/lldb/test/API/commands/expression/fixits/TestFixIts.py index bfe11f6c6fcb9..6b11477e972ef 100644 --- a/lldb/test/API/commands/expression/fixits/TestFixIts.py +++ b/lldb/test/API/commands/expression/fixits/TestFixIts.py @@ -76,7 +76,7 @@ def test_with_target(self): # Now turn off the fixits, and the expression should fail: options.SetAutoApplyFixIts(False) value = frame.EvaluateExpression(two_error_expression, options) - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertTrue(value.GetError().Fail()) error_string = value.GetError().GetCString() self.assertNotEqual( diff --git a/lldb/test/API/commands/expression/options/TestExprOptions.py b/lldb/test/API/commands/expression/options/TestExprOptions.py index 01899f3b97cf4..0cb5921708d2a 100644 --- a/lldb/test/API/commands/expression/options/TestExprOptions.py +++ b/lldb/test/API/commands/expression/options/TestExprOptions.py @@ -56,7 +56,7 @@ def test_expr_options(self): # Make sure it fails if language is set to C: options.SetLanguage(lldb.eLanguageTypeC) val = frame.EvaluateExpression("foo != nullptr", options) - self.assertTrue(val.IsValid()) + self.assertFalse(val.IsValid()) self.assertFalse(val.GetError().Success()) def test_expr_options_lang(self): @@ -83,5 +83,5 @@ def test_expr_options_lang(self): # Make sure we can't retrieve `id` variable if language is set to ObjC: options.SetLanguage(lldb.eLanguageTypeObjC) val = frame.EvaluateExpression("id == 0", options) - self.assertTrue(val.IsValid()) + self.assertFalse(val.IsValid()) self.assertFalse(val.GetError().Success()) diff --git a/lldb/test/API/commands/expression/scoped_enums/TestScopedEnumType.py b/lldb/test/API/commands/expression/scoped_enums/TestScopedEnumType.py index 751e8b8428d62..d10fa3a9c5fae 100644 --- a/lldb/test/API/commands/expression/scoped_enums/TestScopedEnumType.py +++ b/lldb/test/API/commands/expression/scoped_enums/TestScopedEnumType.py @@ -23,10 +23,10 @@ def test(self): ## b is not a Foo value = frame.EvaluateExpression("b == Foo::FooBar") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) ## integral is not implicitly convertible to a scoped enum value = frame.EvaluateExpression("1 == Foo::FooBar") - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) diff --git a/lldb/test/API/commands/expression/timeout/TestCallWithTimeout.py b/lldb/test/API/commands/expression/timeout/TestCallWithTimeout.py index de074e8ff7b09..4817b598f175c 100644 --- a/lldb/test/API/commands/expression/timeout/TestCallWithTimeout.py +++ b/lldb/test/API/commands/expression/timeout/TestCallWithTimeout.py @@ -38,7 +38,7 @@ def test(self): frame = thread.GetFrameAtIndex(0) value = frame.EvaluateExpression(f"wait_a_while({long_time})", options) - self.assertTrue(value.IsValid()) + self.assertFalse(value.IsValid()) self.assertFalse(value.GetError().Success()) # Now do the same thing with the command line command, and make sure it diff --git a/lldb/test/API/python_api/sbvalue_is_valid/TestSBValueIsValid.py b/lldb/test/API/python_api/sbvalue_is_valid/TestSBValueIsValid.py new file mode 100644 index 0000000000000..a3d43c1bdeeb2 --- /dev/null +++ b/lldb/test/API/python_api/sbvalue_is_valid/TestSBValueIsValid.py @@ -0,0 +1,3 @@ +import lldbsuite.test.lldbinline as lldbinline + +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/lldb/test/API/python_api/sbvalue_is_valid/main.cpp b/lldb/test/API/python_api/sbvalue_is_valid/main.cpp new file mode 100644 index 0000000000000..2584a75f63aca --- /dev/null +++ b/lldb/test/API/python_api/sbvalue_is_valid/main.cpp @@ -0,0 +1,7 @@ +int main() { + int i = 42; + return 0; //% v1 = self.frame().EvaluateExpression("test"); v2 = + //self.frame().EvaluateExpression("i"); + //% self.assertFalse(v1.IsValid()) + //% self.assertTrue(v2.IsValid()) +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits