This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA 1/2] framework for varobj type mutation


This patch introduces the framework necessary to support type mutations.
The only language that currently provides a language-specific hook for
that feature is Ada, but the hook remain unimplemented for now. The
actual implementation is tied to the rest of the varobj code for Ada,
and thus will be provided then.

As explained in our previous discussions on the subject, the idea is
that the language would detect whether the type of a varobj has mutated
or not, and if it has, then the core module would simply report that
the varobj's type_changed attribute is "true", and implicitly delete
all the varobj's children.

For instance:

     (gdb) -var-create - * var
     ^done,name="var1",numchild="2",value="{...}",type="pck.var_record",has_more="0"
     [step, step, step, var record now mutated and has 3 fields, now]
     -var-update var1
     ^done,changelist=[{name="var1",in_scope="true",type_changed="true",type_changed="true",new_type="pck.var_record",new_num_children="3",has_more="0"}]

gdb/ChangeLog:

        * varobj.c (ada_value_has_mutated): Add declaration.  New function.
        (struct language_specific): New field "value_has_mutated".
        (languages): Set field "value_has_mutated" in each entry of array.
        (varobj_value_has_mutated): New function.
        (varobj_udpdate): Add handling of type mutation.
        (value_of_root): Add handling of type mutation.
        (ada_value_has_mutated): New function.

Tested on x86_64-linux. OK to commit?

---
 gdb/varobj.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/gdb/varobj.c b/gdb/varobj.c
index 8855ce3..fc49490 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -382,6 +382,9 @@ static struct type *ada_type_of_child (struct varobj *parent, int index);
 static char *ada_value_of_variable (struct varobj *var,
 				    enum varobj_display_formats format);
 
+static int ada_value_has_mutated (struct varobj *var, struct value *new_val,
+				  struct type *new_type);
+
 /* The language specific vector */
 
 struct language_specific
@@ -415,6 +418,21 @@ struct language_specific
   /* The current value of VAR.  */
   char *(*value_of_variable) (struct varobj * var,
 			      enum varobj_display_formats format);
+
+  /* Return nonzero if the type of VAR has mutated.
+
+     VAR's value is still the varobj's previous value, while NEW_VALUE
+     is VAR's new value and NEW_TYPE is the var's new type.  NEW_VALUE
+     may be NULL indicating that there is no value available (the varobj
+     may be out of scope, of may be the child of a null pointer, for
+     instance).  NEW_TYPE, on the other hand, must never be NULL.
+
+     This function should also be able to assume that var's number of
+     children is set (not < 0).
+
+     Languages where types do not mutate can set this to NULL.  */
+  int (*value_has_mutated) (struct varobj *var, struct value *new_value,
+			    struct type *new_type);
 };
 
 /* Array of known source language routines.  */
@@ -429,7 +447,8 @@ static struct language_specific languages[vlang_end] = {
    c_value_of_root,
    c_value_of_child,
    c_type_of_child,
-   c_value_of_variable}
+   c_value_of_variable,
+   NULL /* value_has_mutated */}
   ,
   /* C */
   {
@@ -441,7 +460,8 @@ static struct language_specific languages[vlang_end] = {
    c_value_of_root,
    c_value_of_child,
    c_type_of_child,
-   c_value_of_variable}
+   c_value_of_variable,
+   NULL /* value_has_mutated */}
   ,
   /* C++ */
   {
@@ -453,7 +473,8 @@ static struct language_specific languages[vlang_end] = {
    cplus_value_of_root,
    cplus_value_of_child,
    cplus_type_of_child,
-   cplus_value_of_variable}
+   cplus_value_of_variable,
+   NULL /* value_has_mutated */}
   ,
   /* Java */
   {
@@ -465,7 +486,8 @@ static struct language_specific languages[vlang_end] = {
    java_value_of_root,
    java_value_of_child,
    java_type_of_child,
-   java_value_of_variable},
+   java_value_of_variable,
+   NULL /* value_has_mutated */},
   /* Ada */
   {
    vlang_ada,
@@ -476,7 +498,8 @@ static struct language_specific languages[vlang_end] = {
    ada_value_of_root,
    ada_value_of_child,
    ada_type_of_child,
-   ada_value_of_variable}
+   ada_value_of_variable,
+   ada_value_has_mutated}
 };
 
 /* A little convenience enum for dealing with C++/Java.  */
@@ -1824,6 +1847,30 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
 #endif
 }
 
+/* If NEW_VALUE is the new value of the given varobj (var), return
+   non-zero if var has mutated.  In other words, if the type of
+   the new value is different from the type of the varobj's old
+   value.
+
+   NEW_VALUE may be NULL, if the varobj is now out of scope.  */
+
+static int
+varobj_value_has_mutated (struct varobj *var, struct value *new_value,
+			  struct type *new_type)
+{
+  /* If we haven't previously computed the number of children in var,
+     it does not matter from the front-end's perspective whether
+     the type has mutated or not.  For all intents and purposes,
+     it has not mutated.  */
+  if (var->num_children < 0)
+    return 0;
+
+  if (var->root->lang->value_has_mutated)
+    return var->root->lang->value_has_mutated (var, new_value, new_type);
+  else
+    return 0;
+}
+
 /* Update the values for a variable and its children.  This is a
    two-pronged attack.  First, re-parse the value for the root's
    expression to see if it's changed.  Then go all the way
@@ -1918,9 +1965,28 @@ varobj_update (struct varobj **varp, int explicit)
       /* Update this variable, unless it's a root, which is already
 	 updated.  */
       if (!r.value_installed)
-	{	  
+	{
+	  struct type *new_type;
+
 	  new = value_of_child (v->parent, v->index);
-	  if (install_new_value (v, new, 0 /* type not changed */))
+	  if (new)
+	    new_type = value_type (new);
+	  else
+	    new_type = v->root->lang->type_of_child (v->parent, v->index);
+
+	  if (varobj_value_has_mutated (v, new, new_type))
+	    {
+	      /* The children are no longer valid; delete them now.
+	         Report the fact that its type changed as well.  */
+	      varobj_delete (v, NULL, 1 /* only_children */);
+	      v->num_children = -1;
+	      v->to = -1; /* FIXME: Is that necessary?  */
+	      v->from = -1;
+	      v->type = new_type;
+	      r.type_changed = 1;
+	    }
+
+	  if (install_new_value (v, new, r.type_changed))
 	    {
 	      r.changed = 1;
 	      v->updated = 0;
@@ -2627,7 +2693,28 @@ value_of_root (struct varobj **var_handle, int *type_changed)
       *type_changed = 0;
     }
 
-  return (*var->root->lang->value_of_root) (var_handle);
+  {
+    struct value *value;
+
+    value = (*var->root->lang->value_of_root) (var_handle);
+    if (var->value == NULL || value == NULL)
+      {
+	/* For root varobj-s, a NULL value indicates a scoping issue.
+	   So, nothing to do in terms of checking for mutations.  */
+      }
+    else if (varobj_value_has_mutated (var, value, value_type (value)))
+      {
+	/* The type has mutated, so the children are no longer valid.
+	   Just delete them, and tell our caller that the type has
+	   changed.  */
+	varobj_delete (var, NULL, 1 /* only_children */);
+	var->num_children = -1;
+	var->to = -1; /* FIXME: Is that necessary?  */
+	var->from = -1;
+	*type_changed = 1;
+      }
+    return value;
+  }
 }
 
 /* What is the ``struct value *'' for the INDEX'th child of PARENT?  */
@@ -3844,6 +3931,16 @@ ada_value_of_variable (struct varobj *var, enum varobj_display_formats format)
   return c_value_of_variable (var, format);
 }
 
+/* Implement the "value_has_mutated" routine for Ada.  */
+
+static int
+ada_value_has_mutated (struct varobj *var, struct value *new_val,
+		       struct type *new_type)
+{
+  /* Unimplemented for now.  */
+  return 0;
+}
+
 /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
    with an arbitrary caller supplied DATA pointer.  */
 
-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]