Skip to content

[lldb] Support true/false in ValueObject::SetValueFromCString #115780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 13, 2024

Conversation

JDevlieghere
Copy link
Member

Support "true" and "false" (and "YES" and "NO" in Objective-C) in ValueObject::SetValueFromCString.

Fixes #112597

Support "true" and "false" (and "YES" and "NO" in Objective-C) in
ValueObject::SetValueFromCString.

Fixes llvm#112597
@llvmbot
Copy link
Member

llvmbot commented Nov 11, 2024

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

Changes

Support "true" and "false" (and "YES" and "NO" in Objective-C) in ValueObject::SetValueFromCString.

Fixes #112597


Full diff: https://github.com/llvm/llvm-project/pull/115780.diff

10 Files Affected:

  • (modified) lldb/include/lldb/Target/Language.h (+3-1)
  • (modified) lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp (+8)
  • (modified) lldb/source/Plugins/Language/ObjC/ObjCLanguage.h (+3)
  • (modified) lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp (+8)
  • (modified) lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h (+3)
  • (modified) lldb/source/Target/Language.cpp (+8)
  • (modified) lldb/source/ValueObject/ValueObject.cpp (+15)
  • (modified) lldb/test/API/functionalities/data-formatter/setvaluefromcstring/main.m (+6-1)
  • (modified) lldb/test/API/python_api/value/change_values/TestChangeValueAPI.py (+15-2)
  • (modified) lldb/test/API/python_api/value/change_values/main.c (+9-6)
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);

Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JDevlieghere JDevlieghere merged commit 4714215 into llvm:main Nov 13, 2024
7 checks passed
@JDevlieghere JDevlieghere deleted the issue-112597 branch November 13, 2024 05:18
JDevlieghere added a commit to swiftlang/llvm-project that referenced this pull request Nov 13, 2024
…15780)

Support "true" and "false" (and "YES" and "NO" in Objective-C) in
ValueObject::SetValueFromCString.

Fixes llvm#112597

(cherry picked from commit 4714215)
JDevlieghere added a commit to swiftlang/llvm-project that referenced this pull request Nov 14, 2024
[lldb] Support true/false in ValueObject::SetValueFromCString (llvm#115780)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot change boolean variable with lldb-dap
4 participants