[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