[Lldb-commits] [lldb] [lldb] Support true/false in ValueObject::SetValueFromCString (PR #115780)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 11 14:20:00 PST 2024
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/115780
Support "true" and "false" (and "YES" and "NO" in Objective-C) in ValueObject::SetValueFromCString.
Fixes #112597
>From 3450bca62abbc0e9595b61f663114cd67927ffaf Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Mon, 11 Nov 2024 14:17:17 -0800
Subject: [PATCH] [lldb] Support true/false in ValueObject::SetValueFromCString
Support "true" and "false" (and "YES" and "NO" in Objective-C) in
ValueObject::SetValueFromCString.
Fixes #112597
---
lldb/include/lldb/Target/Language.h | 4 +++-
.../Plugins/Language/ObjC/ObjCLanguage.cpp | 8 ++++++++
.../source/Plugins/Language/ObjC/ObjCLanguage.h | 3 +++
.../ObjCPlusPlus/ObjCPlusPlusLanguage.cpp | 8 ++++++++
.../ObjCPlusPlus/ObjCPlusPlusLanguage.h | 3 +++
lldb/source/Target/Language.cpp | 8 ++++++++
lldb/source/ValueObject/ValueObject.cpp | 15 +++++++++++++++
.../data-formatter/setvaluefromcstring/main.m | 7 ++++++-
.../value/change_values/TestChangeValueAPI.py | 17 +++++++++++++++--
.../API/python_api/value/change_values/main.c | 15 +++++++++------
10 files changed, 78 insertions(+), 10 deletions(-)
diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index c9cddee6baa2da..38ca458159edc7 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -245,7 +245,7 @@ class Language : public PluginInterface {
// a match. But we wouldn't want this to match AnotherA::my_function. The
// user is specifying a truncated path, not a truncated set of characters.
// This function does a language-aware comparison for those purposes.
- virtual bool DemangledNameContainsPath(llvm::StringRef path,
+ virtual bool DemangledNameContainsPath(llvm::StringRef path,
ConstString demangled) const;
// if a language has a custom format for printing variable declarations that
@@ -372,6 +372,8 @@ class Language : public PluginInterface {
return {};
}
+ virtual std::optional<bool> GetBooleanFromString(llvm::StringRef str) const;
+
/// Returns true if this Language supports exception breakpoints on throw via
/// a corresponding LanguageRuntime plugin.
virtual bool SupportsExceptionBreakpointsOnThrow() const { return false; }
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index b44971e36c6d0e..2ae203405cbba0 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -1040,3 +1040,11 @@ bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
}
return false;
}
+
+std::optional<bool>
+ObjCLanguage::GetBooleanFromString(llvm::StringRef str) const {
+ return llvm::StringSwitch<std::optional<bool>>(str)
+ .Case("YES", {true})
+ .Case("NO", {false})
+ .Default({});
+}
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index d9c0cd3c18cfa1..6d265a9be52771 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -194,6 +194,9 @@ class ObjCLanguage : public Language {
llvm::StringRef GetInstanceVariableName() override { return "self"; }
+ virtual std::optional<bool>
+ GetBooleanFromString(llvm::StringRef str) const override;
+
bool SupportsExceptionBreakpointsOnThrow() const override { return true; }
// PluginInterface protocol
diff --git a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
index 79830e529df2d7..0489f4d6ada321 100644
--- a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -43,3 +43,11 @@ Language *ObjCPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
return nullptr;
}
}
+
+std::optional<bool>
+ObjCPlusPlusLanguage::GetBooleanFromString(llvm::StringRef str) const {
+ return llvm::StringSwitch<std::optional<bool>>(str)
+ .Cases("true", "YES", {true})
+ .Cases("false", "NO", {false})
+ .Default({});
+}
diff --git a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
index 1beab9348eb72e..229dffe8462e41 100644
--- a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -44,6 +44,9 @@ class ObjCPlusPlusLanguage : public Language {
llvm::StringRef GetInstanceVariableName() override { return "self"; }
+ virtual std::optional<bool>
+ GetBooleanFromString(llvm::StringRef str) const override;
+
static llvm::StringRef GetPluginNameStatic() { return "objcplusplus"; }
// PluginInterface protocol
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index d0bffe441f6395..a75894ffa4b3b6 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -528,6 +528,14 @@ void Language::GetDefaultExceptionResolverDescription(bool catch_on,
s.Printf("Exception breakpoint (catch: %s throw: %s)",
catch_on ? "on" : "off", throw_on ? "on" : "off");
}
+
+std::optional<bool> Language::GetBooleanFromString(llvm::StringRef str) const {
+ return llvm::StringSwitch<std::optional<bool>>(str)
+ .Case("true", {true})
+ .Case("false", {false})
+ .Default({});
+}
+
// Constructor
Language::Language() = default;
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 4006f6e6fd0a5e..86172ad1b561f9 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -1639,6 +1639,18 @@ addr_t ValueObject::GetPointerValue(AddressType *address_type) {
return address;
}
+static const char *ConvertBoolean(lldb::LanguageType language_type,
+ const char *value_str) {
+ if (Language *language = Language::FindPlugin(language_type))
+ if (auto boolean = language->GetBooleanFromString(value_str))
+ return *boolean ? "1" : "0";
+
+ return llvm::StringSwitch<const char *>(value_str)
+ .Case("true", "1")
+ .Case("false", "0")
+ .Default(value_str);
+}
+
bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
error.Clear();
// Make sure our value is up to date first so that our location and location
@@ -1659,6 +1671,9 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
// If the value is already a scalar, then let the scalar change itself:
m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
} else if (byte_size <= 16) {
+ if (GetCompilerType().IsBoolean())
+ value_str = ConvertBoolean(GetObjectRuntimeLanguage(), value_str);
+
// If the value fits in a scalar, then make a new scalar and again let the
// scalar code do the conversion, then figure out where to put the new
// value.
diff --git a/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m b/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m
index 5f469ccb4922e8..ca0bde04492c52 100644
--- a/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m
+++ b/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m
@@ -2,10 +2,15 @@
int main() {
NSDictionary* dic = @{@1 : @2};
+ BOOL b = NO;
NSLog(@"hello world"); //% dic = self.frame().FindVariable("dic")
//% dic.SetPreferSyntheticValue(True)
//% dic.SetPreferDynamicValue(lldb.eDynamicCanRunTarget)
//% dic.SetValueFromCString("12")
+ //% b = self.frame().FindVariable("b")
+ //% b.SetValueFromCString("YES")
return 0; //% dic = self.frame().FindVariable("dic")
- //% self.assertTrue(dic.GetValueAsUnsigned() == 0xC, "failed to read what I wrote")
+ //% self.assertTrue(dic.GetValueAsUnsigned() == 0xC, "failed to read what I
+ //wrote") % b = self.frame().FindVariable("b") %
+ //self.assertTrue(b.GetValueAsUnsigned() == 0x0, "failed to update b")
}
diff --git a/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py b/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py
index 7d9aa76b9eef93..0d47afd4958733 100644
--- a/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py
+++ b/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py
@@ -2,7 +2,6 @@
Test some SBValue APIs.
"""
-
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -111,6 +110,20 @@ def test_change_value(self):
actual_value, 98765, "Got the right changed value from ptr->second_val"
)
+ ptr_fourth_value = ptr_value.GetChildMemberWithName("fourth_val")
+ self.assertTrue(ptr_fourth_value.IsValid(), "Got fourth_value from ptr")
+ fourth_actual_value = ptr_fourth_value.GetValueAsUnsigned(error, 1)
+ self.assertTrue(error.Success(), "Got an unsigned value for ptr->second_val")
+ self.assertEqual(fourth_actual_value, 0)
+
+ result = ptr_fourth_value.SetValueFromCString("true")
+ self.assertTrue(result, "Success setting ptr->fourth_value.")
+ fourth_actual_value = ptr_fourth_value.GetValueAsSigned(error, 0)
+ self.assertTrue(error.Success(), "Got a changed value from ptr->second_val")
+ self.assertEqual(
+ fourth_actual_value, 1, "Got the right changed value from ptr->fourth_val"
+ )
+
# gcc may set multiple locations for breakpoint
breakpoint.SetEnabled(False)
@@ -125,7 +138,7 @@ def test_change_value(self):
)
expected_value = (
- "Val - 12345 Mine - 55, 98765, 55555555. Ptr - 66, 98765, 66666666"
+ "Val - 12345 Mine - 55, 98765, 55555555, 0. Ptr - 66, 98765, 66666666, 1"
)
stdout = process.GetSTDOUT(1000)
self.assertIn(expected_value, stdout, "STDOUT showed changed values.")
diff --git a/lldb/test/API/python_api/value/change_values/main.c b/lldb/test/API/python_api/value/change_values/main.c
index 01455c01964747..a606eec217d83f 100644
--- a/lldb/test/API/python_api/value/change_values/main.c
+++ b/lldb/test/API/python_api/value/change_values/main.c
@@ -1,5 +1,6 @@
-#include <stdio.h>
+#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
struct foo
@@ -7,21 +8,23 @@ struct foo
uint8_t first_val;
uint32_t second_val;
uint64_t third_val;
+ bool fourth_val;
};
-
+
int main ()
{
int val = 100;
- struct foo mine = {55, 5555, 55555555};
+ struct foo mine = {55, 5555, 55555555, false};
struct foo *ptr = (struct foo *) malloc (sizeof (struct foo));
ptr->first_val = 66;
ptr->second_val = 6666;
ptr->third_val = 66666666;
+ ptr->fourth_val = false;
// Stop here and set values
- printf ("Val - %d Mine - %d, %d, %llu. Ptr - %d, %d, %llu\n", val,
- mine.first_val, mine.second_val, mine.third_val,
- ptr->first_val, ptr->second_val, ptr->third_val);
+ printf("Val - %d Mine - %d, %d, %llu, %d. Ptr - %d, %d, %llu, %d\n", val,
+ mine.first_val, mine.second_val, mine.third_val, mine.fourth_val,
+ ptr->first_val, ptr->second_val, ptr->third_val, ptr->fourth_val);
// Stop here and check values
printf ("This is just another call which we won't make it over %d.", val);
More information about the lldb-commits
mailing list