https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/115780
>From 3450bca62abbc0e9595b61f663114cd67927ffaf Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Mon, 11 Nov 2024 14:17:17 -0800 Subject: [PATCH 1/3] [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); >From c7f0aea18361985c54924d3c0f88a2b9ac185df4 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Mon, 11 Nov 2024 14:39:18 -0800 Subject: [PATCH 2/3] Debork test --- .../data-formatter/setvaluefromcstring/main.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m b/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m index ca0bde04492c52..404306d4381bd3 100644 --- a/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m +++ b/lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m @@ -10,7 +10,7 @@ int main() { //% 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") % b = self.frame().FindVariable("b") % - //self.assertTrue(b.GetValueAsUnsigned() == 0x0, "failed to update b") + //% 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") } >From 11533df3c0ce163ef4c3b6a34f6aa5fec53a8547 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Tue, 12 Nov 2024 17:02:20 -0800 Subject: [PATCH 3/3] Test that "NO" doesn't work for C code --- .../value/change_values/TestChangeValueAPI.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) 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 0d47afd4958733..4c253faccf7c9c 100644 --- a/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py +++ b/lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py @@ -111,19 +111,29 @@ def test_change_value(self): ) ptr_fourth_value = ptr_value.GetChildMemberWithName("fourth_val") - self.assertTrue(ptr_fourth_value.IsValid(), "Got fourth_value from ptr") + self.assertTrue(ptr_fourth_value.IsValid(), "Got fourth_val from ptr") fourth_actual_value = ptr_fourth_value.GetValueAsUnsigned(error, 1) - self.assertTrue(error.Success(), "Got an unsigned value for ptr->second_val") + self.assertTrue(error.Success(), "Got an unsigned value for ptr->fourth_val") self.assertEqual(fourth_actual_value, 0) result = ptr_fourth_value.SetValueFromCString("true") - self.assertTrue(result, "Success setting ptr->fourth_value.") + self.assertTrue(result, "Success setting ptr->fourth_val.") fourth_actual_value = ptr_fourth_value.GetValueAsSigned(error, 0) - self.assertTrue(error.Success(), "Got a changed value from ptr->second_val") + self.assertTrue(error.Success(), "Got a changed value from ptr->fourth_val") self.assertEqual( fourth_actual_value, 1, "Got the right changed value from ptr->fourth_val" ) + result = ptr_fourth_value.SetValueFromCString("NO") + self.assertFalse(result, "Failed setting ptr->fourth_val.") + fourth_actual_value = ptr_fourth_value.GetValueAsSigned(error, 0) + self.assertTrue(error.Success(), "Got the original value from ptr->fourth_val") + self.assertEqual( + fourth_actual_value, + 1, + "Got the original changed value from ptr->fourth_val", + ) + # gcc may set multiple locations for breakpoint breakpoint.SetEnabled(False) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits