[Lldb-commits] [lldb] [LLDB] Add allow_var_updates to DIL and CanUpdateVar to SetValueFromInteger (PR #186421)

via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 13 08:38:03 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: None (cmtice)

<details>
<summary>Changes</summary>

In preparation for updating DIL to handle assignments, this adds a member variable to the DIL Interpreter indicating whether or not updating program variables is allowed. For invocations from the LLDB command prompt (through "frame variable") we want to allow it, but from other places we might not. Therefore we also add a parameter, allow_var_updates, to the invocations of GetValueForVariableExpressionPath, with a default value of false. Finally, we also add a parameter, CanUpdateVars, with a default value of false, to
ValueObject::SetValueFromInteger, as that will be the main function used to by assignment in DIL.

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


11 Files Affected:

- (modified) lldb/include/lldb/Target/BorrowedStackFrame.h (+2-1) 
- (modified) lldb/include/lldb/Target/StackFrame.h (+2-2) 
- (modified) lldb/include/lldb/ValueObject/DILEval.h (+3-1) 
- (modified) lldb/include/lldb/ValueObject/ValueObject.h (+9-9) 
- (modified) lldb/source/Commands/CommandObjectFrame.cpp (+1-1) 
- (modified) lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp (+1-1) 
- (modified) lldb/source/Plugins/Process/scripted/ScriptedFrame.h (+2-1) 
- (modified) lldb/source/Target/BorrowedStackFrame.cpp (+3-2) 
- (modified) lldb/source/Target/StackFrame.cpp (+6-5) 
- (modified) lldb/source/ValueObject/DILEval.cpp (+4-3) 
- (modified) lldb/source/ValueObject/ValueObject.cpp (+16-15) 


``````````diff
diff --git a/lldb/include/lldb/Target/BorrowedStackFrame.h b/lldb/include/lldb/Target/BorrowedStackFrame.h
index 2a34f2816aed2..d77e482e7717e 100644
--- a/lldb/include/lldb/Target/BorrowedStackFrame.h
+++ b/lldb/include/lldb/Target/BorrowedStackFrame.h
@@ -87,7 +87,8 @@ class BorrowedStackFrame : public StackFrame {
   lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error,
-      lldb::DILMode mode = lldb::eDILModeFull) override;
+      lldb::DILMode mode = lldb::eDILModeFull,
+      bool allow_var_updates = false) override;
 
   bool HasDebugInformation() override;
 
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index fe42be3587433..507dcd58cc267 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -325,7 +325,7 @@ class StackFrame : public ExecutionContextScope,
   virtual lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error,
-      lldb::DILMode mode = lldb::eDILModeFull);
+      lldb::DILMode mode = lldb::eDILModeFull, bool allow_var_updates = false);
 
   /// Determine whether this StackFrame has debug information available or not.
   ///
@@ -621,7 +621,7 @@ class StackFrame : public ExecutionContextScope,
   lldb::ValueObjectSP DILGetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error,
-      lldb::DILMode mode = lldb::eDILModeFull);
+      lldb::DILMode mode = lldb::eDILModeFull, bool allow_var_updates = false);
 
   StackFrame(const StackFrame &) = delete;
   const StackFrame &operator=(const StackFrame &) = delete;
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index a6223c4d998ab..7b3edeb9dfd85 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -41,7 +41,8 @@ class Interpreter : Visitor {
   Interpreter(lldb::TargetSP target, llvm::StringRef expr,
               std::shared_ptr<StackFrame> frame_sp,
               lldb::DynamicValueType use_dynamic, bool use_synthetic,
-              bool fragile_ivar, bool check_ptr_vs_member);
+              bool fragile_ivar, bool check_ptr_vs_member,
+              bool allow_var_updates);
 
   /// Evaluate an ASTNode.
   /// \returns A non-null lldb::ValueObjectSP or an Error.
@@ -130,6 +131,7 @@ class Interpreter : Visitor {
   bool m_use_synthetic;
   bool m_fragile_ivar;
   bool m_check_ptr_vs_member;
+  bool m_allow_var_updates;
 };
 
 } // namespace lldb_private::dil
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index 392c69a4f4bda..27eff58fa1b28 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -453,17 +453,17 @@ class ValueObject {
   /// value to a boolean and return that. Otherwise return an error.
   llvm::Expected<bool> GetValueAsBool();
 
-  /// Update an existing integer ValueObject with a new integer value. This
-  /// is only intended to be used with 'temporary' ValueObjects, i.e. ones that
-  /// are not associated with program variables. It does not update program
-  /// memory, registers, stack, etc.
-  void SetValueFromInteger(const llvm::APInt &value, Status &error);
+  /// Update an existing integer ValueObject with a new integer value. If
+  /// CanUpdateVar is true, will allow updating objects associated with
+  /// program variables; otherwise not.
+  void SetValueFromInteger(const llvm::APInt &value, Status &error,
+                           bool CanUpdateVar = false);
 
   /// Update an existing integer ValueObject with an integer value created
-  /// frome 'new_val_sp'.  This is only intended to be used with 'temporary'
-  /// ValueObjects, i.e. ones that are not associated with program variables.
-  /// It does not update program  memory, registers, stack, etc.
-  void SetValueFromInteger(lldb::ValueObjectSP new_val_sp, Status &error);
+  /// frome 'new_val_sp'. If CanUpdateVar is true, will allow updating objects
+  /// associated with program variables; otherwise not.
+  void SetValueFromInteger(lldb::ValueObjectSP new_val_sp, Status &error,
+                           bool CanUpdateVar = false);
 
   virtual bool SetValueFromCString(const char *value_str, Status &error);
 
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 9133359fbf537..8ecf510044944 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -614,7 +614,7 @@ may even involve JITing and running code in the target program.)");
             lldb::VariableSP var_sp;
             valobj_sp = frame->GetValueForVariableExpressionPath(
                 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
-                var_sp, error);
+                var_sp, error, lldb::eDILModeFull, true);
             if (valobj_sp) {
               result.GetValueObjectList().Append(valobj_sp);
 
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
index 54b65dcaed873..0b7903a96e081 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -317,7 +317,7 @@ lldb::ValueObjectSP ScriptedFrame::GetValueObjectForFrameVariable(
 lldb::ValueObjectSP ScriptedFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
     uint32_t options, lldb::VariableSP &var_sp, Status &error,
-    lldb::DILMode mode) {
+    lldb::DILMode mode, bool allow_var_updates) {
   // Unless the frame implementation knows how to create variables (which it
   // doesn't), we can't construct anything for the variable. This may seem
   // somewhat out of place, but it's basically because of how this API is used -
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
index c2fc1df7724df..66a8e926d0ed1 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h
@@ -77,7 +77,8 @@ class ScriptedFrame : public lldb_private::StackFrame {
   lldb::ValueObjectSP GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error,
-      lldb::DILMode mode = lldb::eDILModeFull) override;
+      lldb::DILMode mode = lldb::eDILModeFull,
+      bool allow_var_updates = false) override;
 
   bool isA(const void *ClassID) const override {
     return ClassID == &ID || StackFrame::isA(ClassID);
diff --git a/lldb/source/Target/BorrowedStackFrame.cpp b/lldb/source/Target/BorrowedStackFrame.cpp
index 5b81a1f05bbfb..6482baaa58130 100644
--- a/lldb/source/Target/BorrowedStackFrame.cpp
+++ b/lldb/source/Target/BorrowedStackFrame.cpp
@@ -99,9 +99,10 @@ BorrowedStackFrame::GetInScopeVariableList(bool get_file_globals,
 
 ValueObjectSP BorrowedStackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
-    VariableSP &var_sp, Status &error, lldb::DILMode mode) {
+    VariableSP &var_sp, Status &error, lldb::DILMode mode,
+    bool allow_var_updates) {
   return m_borrowed_frame_sp->GetValueForVariableExpressionPath(
-      var_expr, use_dynamic, options, var_sp, error, mode);
+      var_expr, use_dynamic, options, var_sp, error, mode, allow_var_updates);
 }
 
 bool BorrowedStackFrame::HasDebugInformation() {
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 9fb26176e43c0..759a6fa83d05d 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -524,13 +524,14 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
 
 ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
-    VariableSP &var_sp, Status &error, lldb::DILMode mode) {
+    VariableSP &var_sp, Status &error, lldb::DILMode mode,
+    bool allow_var_updates) {
   ExecutionContext exe_ctx;
   CalculateExecutionContext(exe_ctx);
   bool use_DIL = exe_ctx.GetTargetRef().GetUseDIL(&exe_ctx);
   if (use_DIL)
-    return DILGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
-                                                var_sp, error, mode);
+    return DILGetValueForVariableExpressionPath(
+        var_expr, use_dynamic, options, var_sp, error, mode, allow_var_updates);
 
   return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
                                                  var_sp, error);
@@ -539,7 +540,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
 ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(
     llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
     uint32_t options, lldb::VariableSP &var_sp, Status &error,
-    lldb::DILMode mode) {
+    lldb::DILMode mode, bool allow_var_updates) {
 
   const bool check_ptr_vs_member =
       (options & eExpressionPathOptionCheckPtrVsMember) != 0;
@@ -568,7 +569,7 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(
   lldb::TargetSP target = this->CalculateTarget();
   dil::Interpreter interpreter(target, var_expr, shared_from_this(),
                                use_dynamic, !no_synth_child, !no_fragile_ivar,
-                               check_ptr_vs_member);
+                               check_ptr_vs_member, allow_var_updates);
 
   auto valobj_or_error = interpreter.Evaluate(**tree_or_error);
   if (!valobj_or_error) {
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index ec9ea8b9618fc..7bd3e6aa6b01c 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -389,11 +389,12 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
 Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
                          std::shared_ptr<StackFrame> frame_sp,
                          lldb::DynamicValueType use_dynamic, bool use_synthetic,
-                         bool fragile_ivar, bool check_ptr_vs_member)
+                         bool fragile_ivar, bool check_ptr_vs_member,
+                         bool allow_var_updates)
     : m_target(std::move(target)), m_expr(expr), m_exe_ctx_scope(frame_sp),
       m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic),
-      m_fragile_ivar(fragile_ivar), m_check_ptr_vs_member(check_ptr_vs_member) {
-}
+      m_fragile_ivar(fragile_ivar), m_check_ptr_vs_member(check_ptr_vs_member),
+      m_allow_var_updates(allow_var_updates) {}
 
 llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
   // Evaluate an AST.
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 0582192ef798c..9600f0a15c04d 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -1202,22 +1202,23 @@ llvm::Expected<bool> ValueObject::GetValueAsBool() {
   return llvm::createStringError("type cannot be converted to bool");
 }
 
-void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
+void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error,
+                                      bool CanUpdateVar) {
   // Verify the current object is an integer object
   CompilerType val_type = GetCompilerType();
   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
       !HasFloatingRepresentation(val_type) && !val_type.IsPointerType() &&
       !val_type.IsScalarType()) {
     error =
-        Status::FromErrorString("current value object is not an integer objet");
+        Status::FromErrorString("current value object is not an scalar object");
     return;
   }
 
-  // Verify the current object is not actually associated with any program
-  // variable.
-  if (GetVariable()) {
+  // Verify, if current object is associated with a program variable, that
+  // we are allowing updating progrma variables in this case.
+  if (GetVariable() && !CanUpdateVar) {
     error = Status::FromErrorString(
-        "current value object is not a temporary object");
+        "Not allowed to update program variables in this case.");
     return;
   }
 
@@ -1241,22 +1242,22 @@ void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
 }
 
 void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
-                                      Status &error) {
+                                      Status &error, bool CanUpdateVar) {
   // Verify the current object is an integer object
   CompilerType val_type = GetCompilerType();
   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
       !HasFloatingRepresentation(val_type) && !val_type.IsPointerType() &&
       !val_type.IsScalarType()) {
     error =
-        Status::FromErrorString("current value object is not an integer objet");
+        Status::FromErrorString("current value object is not an scalar object");
     return;
   }
 
-  // Verify the current object is not actually associated with any program
-  // variable.
-  if (GetVariable()) {
+  // Verify, if current object is associated with a program variable, that
+  // we are allowing updating progrma variables in this case.
+  if (GetVariable() && !CanUpdateVar) {
     error = Status::FromErrorString(
-        "current value object is not a temporary object");
+        "Not allowed to update program variables in this case.");
     return;
   }
 
@@ -1272,13 +1273,13 @@ void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
   if (new_val_type.IsInteger()) {
     auto value_or_err = new_val_sp->GetValueAsAPSInt();
     if (value_or_err)
-      SetValueFromInteger(*value_or_err, error);
+      SetValueFromInteger(*value_or_err, error, CanUpdateVar);
     else
       error = Status::FromErrorString("error getting APSInt from new_val_sp");
   } else if (HasFloatingRepresentation(new_val_type)) {
     auto value_or_err = new_val_sp->GetValueAsAPFloat();
     if (value_or_err)
-      SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
+      SetValueFromInteger(value_or_err->bitcastToAPInt(), error, CanUpdateVar);
     else
       error = Status::FromErrorString("error getting APFloat from new_val_sp");
   } else if (new_val_type.IsPointerType()) {
@@ -1290,7 +1291,7 @@ void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
       if (auto temp = llvm::expectedToOptional(
               new_val_sp->GetCompilerType().GetBitSize(target.get())))
         num_bits = temp.value();
-      SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
+      SetValueFromInteger(llvm::APInt(num_bits, int_val), error, CanUpdateVar);
     } else
       error = Status::FromErrorString("error converting new_val_sp to integer");
   }

``````````

</details>


https://github.com/llvm/llvm-project/pull/186421


More information about the lldb-commits mailing list