Author: Jonas Devlieghere Date: 2024-11-12T21:18:22-08:00 New Revision: 4714215efb0486682feaa3a99162e80a934be8f9
URL: https://github.com/llvm/llvm-project/commit/4714215efb0486682feaa3a99162e80a934be8f9 DIFF: https://github.com/llvm/llvm-project/commit/4714215efb0486682feaa3a99162e80a934be8f9.diff LOG: [lldb] Support true/false in ValueObject::SetValueFromCString (#115780) Support "true" and "false" (and "YES" and "NO" in Objective-C) in ValueObject::SetValueFromCString. Fixes #112597 Added: Modified: lldb/include/lldb/Target/Language.h lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp lldb/source/Plugins/Language/ObjC/ObjCLanguage.h lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h lldb/source/Target/Language.cpp lldb/source/ValueObject/ValueObject.cpp lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py lldb/test/API/python_api/value/change_values/main.c Removed: ################################################################################ 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..404306d4381bd3 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") + //% 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..4c253faccf7c9c 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,30 @@ 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_val from ptr") + fourth_actual_value = ptr_fourth_value.GetValueAsUnsigned(error, 1) + 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_val.") + fourth_actual_value = ptr_fourth_value.GetValueAsSigned(error, 0) + 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) @@ -125,7 +148,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); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits