X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=317f6b47fc3e9a3b7050f1e9a658136b8b148856;hb=725a9891bcc665280fb0f749d47416c8e6ea94b7;hp=ccca0511a2ca7880174913e4bed390ce28d058a7;hpb=2024f65ab8bec1dd6d60cfbd92cca9125d3d8a1b;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/varobj.c b/gdb/varobj.c
index ccca0511a2..317f6b47fc 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -1,11 +1,11 @@
/* Implementation of the GDB variable objects API.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -14,9 +14,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see . */
#include "defs.h"
#include "exceptions.h"
@@ -33,6 +31,8 @@
#include "varobj.h"
#include "vec.h"
+#include "gdbthread.h"
+#include "inferior.h"
/* Non-zero if we want to see trace of varobj level stuff. */
@@ -64,12 +64,25 @@ struct varobj_root
/* Block for which this expression is valid */
struct block *valid_block;
- /* The frame for this expression */
+ /* The frame for this expression. This field is set iff valid_block is
+ not NULL. */
struct frame_id frame;
- /* If 1, "update" always recomputes the frame & valid block
- using the currently selected frame. */
- int use_selected_frame;
+ /* The thread ID that this varobj_root belong to. This field
+ is only valid if valid_block is not NULL.
+ When not 0, indicates which thread 'frame' belongs to.
+ When 0, indicates that the thread list was empty when the varobj_root
+ was created. */
+ int thread_id;
+
+ /* If 1, the -var-update always recomputes the value in the
+ current thread and frame. Otherwise, variable object is
+ always updated in the specific scope/thread/frame */
+ int floating;
+
+ /* Flag that indicates validity: set to 0 when this varobj_root refers
+ to symbols that do not exist anymore. */
+ int is_valid;
/* Language info for this variable and its children */
struct language_specific *lang;
@@ -81,10 +94,6 @@ struct varobj_root
struct varobj_root *next;
};
-typedef struct varobj *varobj_p;
-
-DEF_VEC_P (varobj_p);
-
/* Every variable in the system has a structure of this type defined
for it. This structure holds all information necessary to manipulate
a particular object variable. Members which must be freed are noted. */
@@ -97,6 +106,10 @@ struct varobj
/* NOTE: This is the "expression" */
char *name;
+ /* Alloc'd expression for this child. Can be used to create a
+ root variable corresponding to this child. */
+ char *path_expr;
+
/* The alloc'd name for this variable's object. This is here for
convenience when constructing this object's children. */
char *obj_name;
@@ -104,7 +117,9 @@ struct varobj
/* Index of this variable in its parent or -1 */
int index;
- /* The type of this variable. This may NEVER be NULL. */
+ /* The type of this variable. This can be NULL
+ for artifial variable objects -- currently, the "accessibility"
+ variable objects in C++. */
struct type *type;
/* The value of this expression or subexpression. A NULL value
@@ -133,6 +148,16 @@ struct varobj
/* Last print value. */
char *print_value;
+
+ /* Is this variable frozen. Frozen variables are never implicitly
+ updated by -var-update *
+ or -var-update . */
+ int frozen;
+
+ /* Is the value of this variable intentionally not fetched? It is
+ not fetched if either the variable is frozen, or any parents is
+ frozen. */
+ int not_fetched;
};
struct cpstack
@@ -203,9 +228,8 @@ static struct value *value_of_root (struct varobj **var_handle, int *);
static struct value *value_of_child (struct varobj *parent, int index);
-static int variable_editable (struct varobj *var);
-
-static char *my_value_of_variable (struct varobj *var);
+static char *my_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
static char *value_get_print_value (struct value *value,
enum varobj_display_formats format);
@@ -222,15 +246,16 @@ static char *c_name_of_variable (struct varobj *parent);
static char *c_name_of_child (struct varobj *parent, int index);
+static char *c_path_expr_of_child (struct varobj *child);
+
static struct value *c_value_of_root (struct varobj **var_handle);
static struct value *c_value_of_child (struct varobj *parent, int index);
static struct type *c_type_of_child (struct varobj *parent, int index);
-static int c_variable_editable (struct varobj *var);
-
-static char *c_value_of_variable (struct varobj *var);
+static char *c_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* C++ implementation */
@@ -242,15 +267,16 @@ static char *cplus_name_of_variable (struct varobj *parent);
static char *cplus_name_of_child (struct varobj *parent, int index);
+static char *cplus_path_expr_of_child (struct varobj *child);
+
static struct value *cplus_value_of_root (struct varobj **var_handle);
static struct value *cplus_value_of_child (struct varobj *parent, int index);
static struct type *cplus_type_of_child (struct varobj *parent, int index);
-static int cplus_variable_editable (struct varobj *var);
-
-static char *cplus_value_of_variable (struct varobj *var);
+static char *cplus_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* Java implementation */
@@ -260,15 +286,16 @@ static char *java_name_of_variable (struct varobj *parent);
static char *java_name_of_child (struct varobj *parent, int index);
+static char *java_path_expr_of_child (struct varobj *child);
+
static struct value *java_value_of_root (struct varobj **var_handle);
static struct value *java_value_of_child (struct varobj *parent, int index);
static struct type *java_type_of_child (struct varobj *parent, int index);
-static int java_variable_editable (struct varobj *var);
-
-static char *java_value_of_variable (struct varobj *var);
+static char *java_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* The language specific vector */
@@ -287,6 +314,10 @@ struct language_specific
/* The name of the INDEX'th child of PARENT. */
char *(*name_of_child) (struct varobj * parent, int index);
+ /* Returns the rooted expression of CHILD, which is a variable
+ obtain that has some parent. */
+ char *(*path_expr_of_child) (struct varobj * child);
+
/* The ``struct value *'' of the root variable ROOT. */
struct value *(*value_of_root) (struct varobj ** root_handle);
@@ -296,11 +327,9 @@ struct language_specific
/* The type of the INDEX'th child of PARENT. */
struct type *(*type_of_child) (struct varobj * parent, int index);
- /* Is VAR editable? */
- int (*variable_editable) (struct varobj * var);
-
/* The current value of VAR. */
- char *(*value_of_variable) (struct varobj * var);
+ char *(*value_of_variable) (struct varobj * var,
+ enum varobj_display_formats format);
};
/* Array of known source language routines. */
@@ -311,10 +340,10 @@ static struct language_specific languages[vlang_end] = {
c_number_of_children,
c_name_of_variable,
c_name_of_child,
+ c_path_expr_of_child,
c_value_of_root,
c_value_of_child,
c_type_of_child,
- c_variable_editable,
c_value_of_variable}
,
/* C */
@@ -323,10 +352,10 @@ static struct language_specific languages[vlang_end] = {
c_number_of_children,
c_name_of_variable,
c_name_of_child,
+ c_path_expr_of_child,
c_value_of_root,
c_value_of_child,
c_type_of_child,
- c_variable_editable,
c_value_of_variable}
,
/* C++ */
@@ -335,10 +364,10 @@ static struct language_specific languages[vlang_end] = {
cplus_number_of_children,
cplus_name_of_variable,
cplus_name_of_child,
+ cplus_path_expr_of_child,
cplus_value_of_root,
cplus_value_of_child,
cplus_type_of_child,
- cplus_variable_editable,
cplus_value_of_variable}
,
/* Java */
@@ -347,10 +376,10 @@ static struct language_specific languages[vlang_end] = {
java_number_of_children,
java_name_of_variable,
java_name_of_child,
+ java_path_expr_of_child,
java_value_of_root,
java_value_of_child,
java_type_of_child,
- java_variable_editable,
java_value_of_variable}
};
@@ -429,14 +458,15 @@ varobj_create (char *objname,
{
char *p;
enum varobj_languages lang;
- struct value *value;
+ struct value *value = NULL;
+ int expr_len;
/* Parse and evaluate the expression, filling in as much
of the variable's data as possible */
/* Allow creator to specify context of variable */
if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
- fi = deprecated_selected_frame;
+ fi = deprecated_safe_get_selected_frame ();
else
/* FIXME: cagney/2002-11-23: This code should be doing a
lookup using the frame ID and not just the frame's
@@ -448,7 +478,7 @@ varobj_create (char *objname,
/* frame = -2 means always use selected frame */
if (type == USE_SELECTED_FRAME)
- var->root->use_selected_frame = 1;
+ var->root->floating = 1;
block = NULL;
if (fi != NULL)
@@ -474,28 +504,36 @@ varobj_create (char *objname,
var->format = variable_default_display (var);
var->root->valid_block = innermost_block;
- var->name = savestring (expression, strlen (expression));
+ expr_len = strlen (expression);
+ var->name = savestring (expression, expr_len);
+ /* For a root var, the name and the expr are the same. */
+ var->path_expr = savestring (expression, expr_len);
/* When the frame is different from the current frame,
we must select the appropriate frame before parsing
the expression, otherwise the value will not be current.
Since select_frame is so benign, just call it for all cases. */
- if (fi != NULL)
+ if (innermost_block && fi != NULL)
{
var->root->frame = get_frame_id (fi);
- old_fi = deprecated_selected_frame;
- select_frame (fi);
+ var->root->thread_id = pid_to_thread_id (inferior_ptid);
+ old_fi = get_selected_frame (NULL);
+ select_frame (fi);
}
- /* We definitively need to catch errors here.
+ /* We definitely need to catch errors here.
If evaluate_expression succeeds we got the value we wanted.
But if it fails, we still go on with a call to evaluate_type() */
if (!gdb_evaluate_expression (var->root->exp, &value))
- /* Error getting the value. Try to at least get the
- right type. */
- value = evaluate_type (var->root->exp);
+ {
+ /* Error getting the value. Try to at least get the
+ right type. */
+ struct value *type_only_value = evaluate_type (var->root->exp);
+ var->type = value_type (type_only_value);
+ }
+ else
+ var->type = value_type (value);
- var->type = value_type (value);
install_new_value (var, value, 1 /* Initial assignment */);
/* Set language info */
@@ -652,6 +690,13 @@ varobj_set_display_format (struct varobj *var,
var->format = variable_default_display (var);
}
+ if (varobj_value_is_changeable_p (var)
+ && var->value && !value_lazy (var->value))
+ {
+ free (var->print_value);
+ var->print_value = value_get_print_value (var->value, var->format);
+ }
+
return var->format;
}
@@ -661,6 +706,39 @@ varobj_get_display_format (struct varobj *var)
return var->format;
}
+/* If the variable object is bound to a specific thread, that
+ is its evaluation can always be done in context of a frame
+ inside that thread, returns GDB id of the thread -- which
+ is always positive. Otherwise, returns -1. */
+int
+varobj_get_thread_id (struct varobj *var)
+{
+ if (var->root->valid_block && var->root->thread_id > 0)
+ return var->root->thread_id;
+ else
+ return -1;
+}
+
+void
+varobj_set_frozen (struct varobj *var, int frozen)
+{
+ /* When a variable is unfrozen, we don't fetch its value.
+ The 'not_fetched' flag remains set, so next -var-update
+ won't complain.
+
+ We don't fetch the value, because for structures the client
+ should do -var-update anyway. It would be bad to have different
+ client-size logic for structure and other types. */
+ var->frozen = frozen;
+}
+
+int
+varobj_get_frozen (struct varobj *var)
+{
+ return var->frozen;
+}
+
+
int
varobj_get_num_children (struct varobj *var)
{
@@ -673,42 +751,28 @@ varobj_get_num_children (struct varobj *var)
/* Creates a list of the immediate children of a variable object;
the return code is the number of such children or -1 on error */
-int
-varobj_list_children (struct varobj *var, struct varobj ***childlist)
+VEC (varobj_p)*
+varobj_list_children (struct varobj *var)
{
struct varobj *child;
char *name;
int i;
- /* sanity check: have we been passed a pointer? */
- if (childlist == NULL)
- return -1;
-
- *childlist = NULL;
-
if (var->num_children == -1)
var->num_children = number_of_children (var);
/* If that failed, give up. */
if (var->num_children == -1)
- return -1;
+ return var->children;
/* If we're called when the list of children is not yet initialized,
allocate enough elements in it. */
while (VEC_length (varobj_p, var->children) < var->num_children)
VEC_safe_push (varobj_p, var->children, NULL);
- /* List of children */
- *childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *));
-
for (i = 0; i < var->num_children; i++)
{
- varobj_p existing;
-
- /* Mark as the end in case we bail out */
- *((*childlist) + i) = NULL;
-
- existing = VEC_index (varobj_p, var->children, i);
+ varobj_p existing = VEC_index (varobj_p, var->children, i);
if (existing == NULL)
{
@@ -719,14 +783,9 @@ varobj_list_children (struct varobj *var, struct varobj ***childlist)
existing = create_child (var, i, name);
VEC_replace (varobj_p, var->children, i, existing);
}
-
- *((*childlist) + i) = existing;
}
- /* End of list is marked by a NULL pointer */
- *((*childlist) + i) = NULL;
-
- return var->num_children;
+ return var->children;
}
/* Obtain the type of an object Variable as a string similar to the one gdb
@@ -742,8 +801,9 @@ varobj_get_type (struct varobj *var)
long length;
/* For the "fake" variables, do not return a type. (It's type is
- NULL, too.) */
- if (CPLUS_FAKE_CHILD (var))
+ NULL, too.)
+ Do not return a type for invalid variables as well. */
+ if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid)
return NULL;
stb = mem_fileopen ();
@@ -767,6 +827,23 @@ varobj_get_gdb_type (struct varobj *var)
return var->type;
}
+/* Return a pointer to the full rooted expression of varobj VAR.
+ If it has not been computed yet, compute it. */
+char *
+varobj_get_path_expr (struct varobj *var)
+{
+ if (var->path_expr != NULL)
+ return var->path_expr;
+ else
+ {
+ /* For root varobjs, we initialize path_expr
+ when creating varobj, so here it should be
+ child varobj. */
+ gdb_assert (!is_root_p (var));
+ return (*var->root->lang->path_expr_of_child) (var);
+ }
+}
+
enum varobj_languages
varobj_get_language (struct varobj *var)
{
@@ -778,17 +855,24 @@ varobj_get_attributes (struct varobj *var)
{
int attributes = 0;
- if (variable_editable (var))
+ if (varobj_editable_p (var))
/* FIXME: define masks for attributes */
attributes |= 0x00000001; /* Editable */
return attributes;
}
+char *
+varobj_get_formatted_value (struct varobj *var,
+ enum varobj_display_formats format)
+{
+ return my_value_of_variable (var, format);
+}
+
char *
varobj_get_value (struct varobj *var)
{
- return my_value_of_variable (var);
+ return my_value_of_variable (var, var->format);
}
/* Set the value of an object variable (if it is editable) to the
@@ -808,55 +892,51 @@ varobj_set_value (struct varobj *var, char *expression)
struct expression *exp;
struct value *value;
int saved_input_radix = input_radix;
+ char *s = expression;
+ int i;
- if (var->value != NULL && variable_editable (var))
- {
- char *s = expression;
- int i;
-
- input_radix = 10; /* ALWAYS reset to decimal temporarily */
- exp = parse_exp_1 (&s, 0, 0);
- if (!gdb_evaluate_expression (exp, &value))
- {
- /* We cannot proceed without a valid expression. */
- xfree (exp);
- return 0;
- }
+ gdb_assert (varobj_editable_p (var));
- /* All types that are editable must also be changeable. */
- gdb_assert (varobj_value_is_changeable_p (var));
-
- /* The value of a changeable variable object must not be lazy. */
- gdb_assert (!value_lazy (var->value));
-
- /* Need to coerce the input. We want to check if the
- value of the variable object will be different
- after assignment, and the first thing value_assign
- does is coerce the input.
- For example, if we are assigning an array to a pointer variable we
- should compare the pointer with the the array's address, not with the
- array's content. */
- value = coerce_array (value);
-
- /* The new value may be lazy. gdb_value_assign, or
- rather value_contents, will take care of this.
- If fetching of the new value will fail, gdb_value_assign
- with catch the exception. */
- if (!gdb_value_assign (var->value, value, &val))
- return 0;
-
- /* If the value has changed, record it, so that next -var-update can
- report this change. If a variable had a value of '1', we've set it
- to '333' and then set again to '1', when -var-update will report this
- variable as changed -- because the first assignment has set the
- 'updated' flag. There's no need to optimize that, because return value
- of -var-update should be considered an approximation. */
- var->updated = install_new_value (var, val, 0 /* Compare values. */);
- input_radix = saved_input_radix;
- return 1;
+ input_radix = 10; /* ALWAYS reset to decimal temporarily */
+ exp = parse_exp_1 (&s, 0, 0);
+ if (!gdb_evaluate_expression (exp, &value))
+ {
+ /* We cannot proceed without a valid expression. */
+ xfree (exp);
+ return 0;
}
- return 0;
+ /* All types that are editable must also be changeable. */
+ gdb_assert (varobj_value_is_changeable_p (var));
+
+ /* The value of a changeable variable object must not be lazy. */
+ gdb_assert (!value_lazy (var->value));
+
+ /* Need to coerce the input. We want to check if the
+ value of the variable object will be different
+ after assignment, and the first thing value_assign
+ does is coerce the input.
+ For example, if we are assigning an array to a pointer variable we
+ should compare the pointer with the the array's address, not with the
+ array's content. */
+ value = coerce_array (value);
+
+ /* The new value may be lazy. gdb_value_assign, or
+ rather value_contents, will take care of this.
+ If fetching of the new value will fail, gdb_value_assign
+ with catch the exception. */
+ if (!gdb_value_assign (var->value, value, &val))
+ return 0;
+
+ /* If the value has changed, record it, so that next -var-update can
+ report this change. If a variable had a value of '1', we've set it
+ to '333' and then set again to '1', when -var-update will report this
+ variable as changed -- because the first assignment has set the
+ 'updated' flag. There's no need to optimize that, because return value
+ of -var-update should be considered an approximation. */
+ var->updated = install_new_value (var, val, 0 /* Compare values. */);
+ input_radix = saved_input_radix;
+ return 1;
}
/* Returns a malloc'ed list with all root variable objects */
@@ -906,6 +986,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
int changeable;
int need_to_fetch;
int changed = 0;
+ int intentionally_not_fetched = 0;
+ char *print_value = NULL;
/* We need to know the varobj's type to decide if the value should
be fetched or not. C++ fake children (public/protected/private) don't have
@@ -941,7 +1023,20 @@ install_new_value (struct varobj *var, struct value *value, int initial)
will be lazy, which means we've lost that old value. */
if (need_to_fetch && value && value_lazy (value))
{
- if (!gdb_value_fetch_lazy (value))
+ struct varobj *parent = var->parent;
+ int frozen = var->frozen;
+ for (; !frozen && parent; parent = parent->parent)
+ frozen |= parent->frozen;
+
+ if (frozen && initial)
+ {
+ /* For variables that are frozen, or are children of frozen
+ variables, we don't do fetch on initial assignment.
+ For non-initial assignemnt we do the fetch, since it means we're
+ explicitly asked to compare the new value with the old one. */
+ intentionally_not_fetched = 1;
+ }
+ else if (!gdb_value_fetch_lazy (value))
{
/* Set the value to NULL, so that for the next -var-update,
we don't try to compare the new value with this value,
@@ -950,12 +1045,17 @@ install_new_value (struct varobj *var, struct value *value, int initial)
}
}
+ /* Below, we'll be comparing string rendering of old and new
+ values. Don't get string rendering if the value is
+ lazy -- if it is, the code above has decided that the value
+ should not be fetched. */
+ if (value && !value_lazy (value))
+ print_value = value_get_print_value (value, var->format);
+
/* If the type is changeable, compare the old and the new values.
If this is the initial assignment, we don't have any old value
to compare with. */
- if (initial)
- var->print_value = value_get_print_value (value, var->format);
- else if (changeable)
+ if (!initial && changeable)
{
/* If the value of the varobj was changed by -var-set-value, then the
value in the varobj and in the target is the same. However, that value
@@ -963,49 +1063,51 @@ install_new_value (struct varobj *var, struct value *value, int initial)
-var-update. So need to the varobj as changed. */
if (var->updated)
{
- xfree (var->print_value);
- var->print_value = value_get_print_value (value, var->format);
changed = 1;
}
else
{
/* Try to compare the values. That requires that both
values are non-lazy. */
-
- /* Quick comparison of NULL values. */
- if (var->value == NULL && value == NULL)
+ if (var->not_fetched && value_lazy (var->value))
+ {
+ /* This is a frozen varobj and the value was never read.
+ Presumably, UI shows some "never read" indicator.
+ Now that we've fetched the real value, we need to report
+ this varobj as changed so that UI can show the real
+ value. */
+ changed = 1;
+ }
+ else if (var->value == NULL && value == NULL)
/* Equal. */
;
else if (var->value == NULL || value == NULL)
{
- xfree (var->print_value);
- var->print_value = value_get_print_value (value, var->format);
changed = 1;
}
else
{
- char *print_value;
gdb_assert (!value_lazy (var->value));
gdb_assert (!value_lazy (value));
- print_value = value_get_print_value (value, var->format);
gdb_assert (var->print_value != NULL && print_value != NULL);
if (strcmp (var->print_value, print_value) != 0)
- {
- xfree (var->print_value);
- var->print_value = print_value;
- changed = 1;
- }
- else
- xfree (print_value);
+ changed = 1;
}
}
}
/* We must always keep the new value, since children depend on it. */
- if (var->value != NULL)
+ if (var->value != NULL && var->value != value)
value_free (var->value);
var->value = value;
+ if (var->print_value)
+ xfree (var->print_value);
+ var->print_value = print_value;
+ if (value && value_lazy (value) && intentionally_not_fetched)
+ var->not_fetched = 1;
+ else
+ var->not_fetched = 0;
var->updated = 0;
gdb_assert (!var->value || value_type (var->value));
@@ -1018,23 +1120,25 @@ install_new_value (struct varobj *var, struct value *value, int initial)
expression to see if it's changed. Then go all the way
through its children, reconstructing them and noting if they've
changed.
- Return value:
- -1 if there was an error updating the varobj
- -2 if the type changed
- Otherwise it is the number of children + parent changed
+ Return value:
+ < 0 for error values, see varobj.h.
+ Otherwise it is the number of children + parent changed.
- Only root variables can be updated...
+ The EXPLICIT parameter specifies if this call is result
+ of MI request to update this specific variable, or
+ result of implicit -var-update *. For implicit request, we don't
+ update frozen variables.
NOTE: This function may delete the caller's varobj. If it
- returns -2, then it has done this and VARP will be modified
- to point to the new varobj. */
+ returns TYPE_CHANGED, then it has done this and VARP will be modified
+ to point to the new varobj. */
int
-varobj_update (struct varobj **varp, struct varobj ***changelist)
+varobj_update (struct varobj **varp, struct varobj ***changelist,
+ int explicit)
{
int changed = 0;
- int error = 0;
- int type_changed;
+ int type_changed = 0;
int i;
int vleft;
struct varobj *v;
@@ -1043,59 +1147,56 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
struct value *new;
VEC (varobj_p) *stack = NULL;
VEC (varobj_p) *result = NULL;
- struct frame_id old_fid;
struct frame_info *fi;
- /* sanity check: have we been passed a pointer? */
- if (changelist == NULL)
- return -1;
+ /* sanity check: have we been passed a pointer? */
+ gdb_assert (changelist);
- /* Only root variables can be updated... */
- if (!is_root_p (*varp))
- /* Not a root var */
- return -1;
-
- /* Save the selected stack frame, since we will need to change it
- in order to evaluate expressions. */
- old_fid = get_frame_id (deprecated_selected_frame);
-
- /* Update the root variable. value_of_root can return NULL
- if the variable is no longer around, i.e. we stepped out of
- the frame in which a local existed. We are letting the
- value_of_root variable dispose of the varobj if the type
- has changed. */
- type_changed = 1;
- new = value_of_root (varp, &type_changed);
-
- /* Restore selected frame */
- fi = frame_find_by_id (old_fid);
- if (fi)
- select_frame (fi);
+ /* Frozen means frozen -- we don't check for any change in
+ this varobj, including its going out of scope, or
+ changing type. One use case for frozen varobjs is
+ retaining previously evaluated expressions, and we don't
+ want them to be reevaluated at all. */
+ if (!explicit && (*varp)->frozen)
+ return 0;
- /* If this is a "use_selected_frame" varobj, and its type has changed,
- them note that it's changed. */
- if (type_changed)
- VEC_safe_push (varobj_p, result, *varp);
+ if (!(*varp)->root->is_valid)
+ return INVALID;
- if (install_new_value ((*varp), new, type_changed))
+ if ((*varp)->root->rootvar == *varp)
{
- /* If type_changed is 1, install_new_value will never return
- non-zero, so we'll never report the same variable twice. */
- gdb_assert (!type_changed);
- VEC_safe_push (varobj_p, result, *varp);
- }
+ /* Update the root variable. value_of_root can return NULL
+ if the variable is no longer around, i.e. we stepped out of
+ the frame in which a local existed. We are letting the
+ value_of_root variable dispose of the varobj if the type
+ has changed. */
+ new = value_of_root (varp, &type_changed);
+
+ /* If this is a floating varobj, and its type has changed,
+ them note that it's changed. */
+ if (type_changed)
+ VEC_safe_push (varobj_p, result, *varp);
+
+ if (install_new_value ((*varp), new, type_changed))
+ {
+ /* If type_changed is 1, install_new_value will never return
+ non-zero, so we'll never report the same variable twice. */
+ gdb_assert (!type_changed);
+ VEC_safe_push (varobj_p, result, *varp);
+ }
- if (new == NULL)
- {
- /* This means the varobj itself is out of scope.
- Report it. */
- VEC_free (varobj_p, result);
- return -1;
+ if (new == NULL)
+ {
+ /* This means the varobj itself is out of scope.
+ Report it. */
+ VEC_free (varobj_p, result);
+ return NOT_IN_SCOPE;
+ }
}
VEC_safe_push (varobj_p, stack, *varp);
- /* Walk through the children, reconstructing them all. */
+ /* Walk through the children, reconstructing them all. */
while (!VEC_empty (varobj_p, stack))
{
v = VEC_pop (varobj_p, stack);
@@ -1108,13 +1209,13 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
{
varobj_p c = VEC_index (varobj_p, v->children, i);
/* Child may be NULL if explicitly deleted by -var-delete. */
- if (c != NULL)
+ if (c != NULL && !c->frozen)
VEC_safe_push (varobj_p, stack, c);
}
/* Update this variable, unless it's a root, which is already
updated. */
- if (v != *varp)
+ if (v->root->rootvar != v)
{
new = value_of_child (v->parent, v->index);
if (install_new_value (v, new, 0 /* type not changed */))
@@ -1126,7 +1227,7 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
}
}
- /* Alloc (changed + 1) list entries */
+ /* Alloc (changed + 1) list entries. */
changed = VEC_length (varobj_p, result);
*changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
cv = *changelist;
@@ -1139,8 +1240,11 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
}
*cv = 0;
+ VEC_free (varobj_p, stack);
+ VEC_free (varobj_p, result);
+
if (type_changed)
- return -2;
+ return TYPE_CHANGED;
else
return changed;
}
@@ -1179,6 +1283,8 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp,
for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
{
varobj_p child = VEC_index (varobj_p, var->children, i);
+ if (!child)
+ continue;
if (!remove_from_parent_p)
child->parent = NULL;
delete_variable_1 (resultp, delcountp, child, 0, only_children_p);
@@ -1382,6 +1488,7 @@ new_variable (void)
var = (struct varobj *) xmalloc (sizeof (struct varobj));
var->name = NULL;
+ var->path_expr = NULL;
var->obj_name = NULL;
var->index = -1;
var->type = NULL;
@@ -1393,6 +1500,8 @@ new_variable (void)
var->root = NULL;
var->updated = 0;
var->print_value = NULL;
+ var->frozen = 0;
+ var->not_fetched = 0;
return var;
}
@@ -1407,8 +1516,9 @@ new_root_variable (void)
var->root->exp = NULL;
var->root->valid_block = NULL;
var->root->frame = null_frame_id;
- var->root->use_selected_frame = 0;
+ var->root->floating = 0;
var->root->rootvar = NULL;
+ var->root->is_valid = 1;
return var;
}
@@ -1427,6 +1537,7 @@ free_variable (struct varobj *var)
xfree (var->name);
xfree (var->obj_name);
xfree (var->print_value);
+ xfree (var->path_expr);
xfree (var);
}
@@ -1600,16 +1711,15 @@ name_of_child (struct varobj *var, int index)
return (*var->root->lang->name_of_child) (var, index);
}
-/* What is the ``struct value *'' of the root variable VAR?
- TYPE_CHANGED controls what to do if the type of a
- use_selected_frame = 1 variable changes. On input,
- TYPE_CHANGED = 1 means discard the old varobj, and replace
- it with this one. TYPE_CHANGED = 0 means leave it around.
- NB: In both cases, var_handle will point to the new varobj,
- so if you use TYPE_CHANGED = 0, you will have to stash the
- old varobj pointer away somewhere before calling this.
- On return, TYPE_CHANGED will be 1 if the type has changed, and
- 0 otherwise. */
+/* What is the ``struct value *'' of the root variable VAR?
+ For floating variable object, evaluation can get us a value
+ of different type from what is stored in varobj already. In
+ that case:
+ - *type_changed will be set to 1
+ - old varobj will be freed, and new one will be
+ created, with the same name.
+ - *var_handle will be set to the new varobj
+ Otherwise, *type_changed will be set to 0. */
static struct value *
value_of_root (struct varobj **var_handle, int *type_changed)
{
@@ -1626,40 +1736,47 @@ value_of_root (struct varobj **var_handle, int *type_changed)
if (!is_root_p (var))
return NULL;
- if (var->root->use_selected_frame)
+ if (var->root->floating)
{
struct varobj *tmp_var;
char *old_type, *new_type;
- old_type = varobj_get_type (var);
+
tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
USE_SELECTED_FRAME);
if (tmp_var == NULL)
{
return NULL;
}
+ old_type = varobj_get_type (var);
new_type = varobj_get_type (tmp_var);
if (strcmp (old_type, new_type) == 0)
{
+ /* The expression presently stored inside var->root->exp
+ remembers the locations of local variables relatively to
+ the frame where the expression was created (in DWARF location
+ button, for example). Naturally, those locations are not
+ correct in other frames, so update the expression. */
+
+ struct expression *tmp_exp = var->root->exp;
+ var->root->exp = tmp_var->root->exp;
+ tmp_var->root->exp = tmp_exp;
+
varobj_delete (tmp_var, NULL, 0);
*type_changed = 0;
}
else
{
- if (*type_changed)
- {
- tmp_var->obj_name =
- savestring (var->obj_name, strlen (var->obj_name));
- varobj_delete (var, NULL, 0);
- }
- else
- {
- tmp_var->obj_name = varobj_gen_name ();
- }
+ tmp_var->obj_name =
+ savestring (var->obj_name, strlen (var->obj_name));
+ varobj_delete (var, NULL, 0);
+
install_variable (tmp_var);
*var_handle = tmp_var;
var = *var_handle;
*type_changed = 1;
}
+ xfree (old_type);
+ xfree (new_type);
}
else
{
@@ -1680,19 +1797,14 @@ value_of_child (struct varobj *parent, int index)
return value;
}
-/* Is this variable editable? Use the variable's type to make
- this determination. */
-static int
-variable_editable (struct varobj *var)
-{
- return (*var->root->lang->variable_editable) (var);
-}
-
/* GDB already has a command called "value_of_variable". Sigh. */
static char *
-my_value_of_variable (struct varobj *var)
+my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
- return (*var->root->lang->value_of_variable) (var);
+ if (var->root->is_valid)
+ return (*var->root->lang->value_of_variable) (var, format);
+ else
+ return NULL;
}
static char *
@@ -1709,13 +1821,41 @@ value_get_print_value (struct value *value, enum varobj_display_formats format)
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
- common_val_print (value, stb, format_code[(int) format], 1, 0, 0);
+ common_val_print (value, stb, format_code[(int) format], 1, 0, 0,
+ current_language);
thevalue = ui_file_xstrdup (stb, &dummy);
do_cleanups (old_chain);
return thevalue;
}
+int
+varobj_editable_p (struct varobj *var)
+{
+ struct type *type;
+ struct value *value;
+
+ if (!(var->root->is_valid && var->value && VALUE_LVAL (var->value)))
+ return 0;
+
+ type = get_value_type (var);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ return 0;
+ break;
+
+ default:
+ return 1;
+ break;
+ }
+}
+
/* Return non-zero if changes in value of VAR
must be detected and reported by -var-update.
Return zero is -var-update should never report
@@ -1751,6 +1891,15 @@ varobj_value_is_changeable_p (struct varobj *var)
return r;
}
+/* Return 1 if that varobj is floating, that is is always evaluated in the
+ selected frame, and not bound to thread/frame. Such variable objects
+ are created using '@' as frame specifier to -var-create. */
+int
+varobj_floating_p (struct varobj *var)
+{
+ return var->root->floating;
+}
+
/* Given the value and the type of a variable object,
adjust the value and type to those necessary
for getting children of the variable object.
@@ -1761,13 +1910,21 @@ varobj_value_is_changeable_p (struct varobj *var)
Both TYPE and *TYPE should be non-null. VALUE
can be null if we want to only translate type.
*VALUE can be null as well -- if the parent
- value is not known. */
+ value is not known.
+
+ If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1
+ depending on whether pointer was deferenced
+ in this function. */
static void
adjust_value_for_child_access (struct value **value,
- struct type **type)
+ struct type **type,
+ int *was_ptr)
{
gdb_assert (type && *type);
+ if (was_ptr)
+ *was_ptr = 0;
+
*type = check_typedef (*type);
/* The type of value stored in varobj, that is passed
@@ -1786,8 +1943,14 @@ adjust_value_for_child_access (struct value **value,
|| TYPE_CODE (target_type) == TYPE_CODE_UNION)
{
if (value && *value)
- gdb_value_ind (*value, value);
+ {
+ int success = gdb_value_ind (*value, value);
+ if (!success)
+ *value = NULL;
+ }
*type = target_type;
+ if (was_ptr)
+ *was_ptr = 1;
}
}
@@ -1804,7 +1967,7 @@ c_number_of_children (struct varobj *var)
int children = 0;
struct type *target;
- adjust_value_for_child_access (NULL, &type);
+ adjust_value_for_child_access (NULL, &type, NULL);
target = get_target_type (type);
switch (TYPE_CODE (type))
@@ -1900,10 +2063,13 @@ value_struct_element_index (struct value *value, int type_index)
to NULL. */
static void
c_describe_child (struct varobj *parent, int index,
- char **cname, struct value **cvalue, struct type **ctype)
+ char **cname, struct value **cvalue, struct type **ctype,
+ char **cfull_expression)
{
struct value *value = parent->value;
struct type *type = get_value_type (parent);
+ char *parent_expression = NULL;
+ int was_ptr;
if (cname)
*cname = NULL;
@@ -1911,8 +2077,12 @@ c_describe_child (struct varobj *parent, int index,
*cvalue = NULL;
if (ctype)
*ctype = NULL;
-
- adjust_value_for_child_access (&value, &type);
+ if (cfull_expression)
+ {
+ *cfull_expression = NULL;
+ parent_expression = varobj_get_path_expr (parent);
+ }
+ adjust_value_for_child_access (&value, &type, &was_ptr);
switch (TYPE_CODE (type))
{
@@ -1932,6 +2102,12 @@ c_describe_child (struct varobj *parent, int index,
if (ctype)
*ctype = get_target_type (type);
+ if (cfull_expression)
+ *cfull_expression = xstrprintf ("(%s)[%d]", parent_expression,
+ index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+
+
break;
case TYPE_CODE_STRUCT:
@@ -1951,6 +2127,13 @@ c_describe_child (struct varobj *parent, int index,
if (ctype)
*ctype = TYPE_FIELD_TYPE (type, index);
+ if (cfull_expression)
+ {
+ char *join = was_ptr ? "->" : ".";
+ *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join,
+ TYPE_FIELD_NAME (type, index));
+ }
+
break;
case TYPE_CODE_PTR:
@@ -1958,13 +2141,20 @@ c_describe_child (struct varobj *parent, int index,
*cname = xstrprintf ("*%s", parent->name);
if (cvalue && value)
- gdb_value_ind (value, cvalue);
+ {
+ int success = gdb_value_ind (value, cvalue);
+ if (!success)
+ *cvalue = NULL;
+ }
/* Don't use get_target_type because it calls
check_typedef and here, we want to show the true
declared type of the variable. */
if (ctype)
*ctype = TYPE_TARGET_TYPE (type);
+
+ if (cfull_expression)
+ *cfull_expression = xstrprintf ("*(%s)", parent_expression);
break;
@@ -1972,6 +2162,8 @@ c_describe_child (struct varobj *parent, int index,
/* This should not happen */
if (cname)
*cname = xstrdup ("???");
+ if (cfull_expression)
+ *cfull_expression = xstrdup ("???");
/* Don't set value and type, we don't know then. */
}
}
@@ -1980,56 +2172,89 @@ static char *
c_name_of_child (struct varobj *parent, int index)
{
char *name;
- c_describe_child (parent, index, &name, NULL, NULL);
+ c_describe_child (parent, index, &name, NULL, NULL, NULL);
return name;
}
+static char *
+c_path_expr_of_child (struct varobj *child)
+{
+ c_describe_child (child->parent, child->index, NULL, NULL, NULL,
+ &child->path_expr);
+ return child->path_expr;
+}
+
+/* If frame associated with VAR can be found, switch
+ to it and return 1. Otherwise, return 0. */
+static int
+check_scope (struct varobj *var)
+{
+ struct frame_info *fi;
+ int scope;
+
+ fi = frame_find_by_id (var->root->frame);
+ scope = fi != NULL;
+
+ if (fi)
+ {
+ CORE_ADDR pc = get_frame_pc (fi);
+ if (pc < BLOCK_START (var->root->valid_block) ||
+ pc >= BLOCK_END (var->root->valid_block))
+ scope = 0;
+ else
+ select_frame (fi);
+ }
+ return scope;
+}
+
static struct value *
c_value_of_root (struct varobj **var_handle)
{
struct value *new_val = NULL;
struct varobj *var = *var_handle;
struct frame_info *fi;
- int within_scope;
-
+ int within_scope = 0;
+ struct cleanup *back_to;
+
/* Only root variables can be updated... */
if (!is_root_p (var))
/* Not a root var */
return NULL;
+ back_to = make_cleanup_restore_current_thread (
+ inferior_ptid, get_frame_id (deprecated_safe_get_selected_frame ()));
/* Determine whether the variable is still around. */
- if (var->root->valid_block == NULL || var->root->use_selected_frame)
+ if (var->root->valid_block == NULL || var->root->floating)
within_scope = 1;
+ else if (var->root->thread_id == 0)
+ {
+ /* The program was single-threaded when the variable object was
+ created. Technically, it's possible that the program became
+ multi-threaded since then, but we don't support such
+ scenario yet. */
+ within_scope = check_scope (var);
+ }
else
{
- fi = frame_find_by_id (var->root->frame);
- within_scope = fi != NULL;
- /* FIXME: select_frame could fail */
- if (fi)
+ ptid_t ptid = thread_id_to_pid (var->root->thread_id);
+ if (in_thread_list (ptid))
{
- CORE_ADDR pc = get_frame_pc (fi);
- if (pc < BLOCK_START (var->root->valid_block) ||
- pc >= BLOCK_END (var->root->valid_block))
- within_scope = 0;
- else
- select_frame (fi);
- }
+ switch_to_thread (ptid);
+ within_scope = check_scope (var);
+ }
}
if (within_scope)
{
/* We need to catch errors here, because if evaluate
- expression fails we just want to make val->error = 1 and
- go on */
- if (gdb_evaluate_expression (var->root->exp, &new_val))
- {
- release_value (new_val);
- }
-
+ expression fails we want to just return NULL. */
+ gdb_evaluate_expression (var->root->exp, &new_val);
return new_val;
}
+ do_cleanups (back_to);
+
return NULL;
}
@@ -2037,9 +2262,7 @@ static struct value *
c_value_of_child (struct varobj *parent, int index)
{
struct value *value = NULL;
- c_describe_child (parent, index, NULL, &value, NULL);
- if (value != NULL)
- release_value (value);
+ c_describe_child (parent, index, NULL, &value, NULL, NULL);
return value;
}
@@ -2048,31 +2271,12 @@ static struct type *
c_type_of_child (struct varobj *parent, int index)
{
struct type *type = NULL;
- c_describe_child (parent, index, NULL, NULL, &type);
+ c_describe_child (parent, index, NULL, NULL, &type, NULL);
return type;
}
-static int
-c_variable_editable (struct varobj *var)
-{
- switch (TYPE_CODE (get_value_type (var)))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_FUNC:
- case TYPE_CODE_METHOD:
- return 0;
- break;
-
- default:
- return 1;
- break;
- }
-}
-
static char *
-c_value_of_variable (struct varobj *var)
+c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* BOGUS: if val_print sees a struct/class, or a reference to one,
it will print out its children instead of "{...}". So we need to
@@ -2109,9 +2313,21 @@ c_value_of_variable (struct varobj *var)
}
else
{
+ if (var->not_fetched && value_lazy (var->value))
+ /* Frozen variable and no value yet. We don't
+ implicitly fetch the value. MI response will
+ use empty string for the value, which is OK. */
+ return NULL;
+
gdb_assert (varobj_value_is_changeable_p (var));
gdb_assert (!value_lazy (var->value));
- return value_get_print_value (var->value, var->format);
+
+ /* If the specified format is the current one,
+ we can reuse print_value */
+ if (format == var->format)
+ return xstrdup (var->print_value);
+ else
+ return value_get_print_value (var->value, format);
}
}
}
@@ -2132,7 +2348,7 @@ cplus_number_of_children (struct varobj *var)
if (!CPLUS_FAKE_CHILD (var))
{
type = get_value_type (var);
- adjust_value_for_child_access (NULL, &type);
+ adjust_value_for_child_access (NULL, &type, NULL);
if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
((TYPE_CODE (type)) == TYPE_CODE_UNION))
@@ -2159,7 +2375,7 @@ cplus_number_of_children (struct varobj *var)
int kids[3];
type = get_value_type (var->parent);
- adjust_value_for_child_access (NULL, &type);
+ adjust_value_for_child_access (NULL, &type, NULL);
cplus_class_num_children (type, kids);
if (strcmp (var->name, "public") == 0)
@@ -2230,11 +2446,14 @@ match_accessibility (struct type *type, int index, enum accessibility acc)
static void
cplus_describe_child (struct varobj *parent, int index,
- char **cname, struct value **cvalue, struct type **ctype)
+ char **cname, struct value **cvalue, struct type **ctype,
+ char **cfull_expression)
{
- char *name = 0;
+ char *name = NULL;
struct value *value;
struct type *type;
+ int was_ptr;
+ char *parent_expression = NULL;
if (cname)
*cname = NULL;
@@ -2242,24 +2461,30 @@ cplus_describe_child (struct varobj *parent, int index,
*cvalue = NULL;
if (ctype)
*ctype = NULL;
-
+ if (cfull_expression)
+ *cfull_expression = NULL;
if (CPLUS_FAKE_CHILD (parent))
{
value = parent->parent->value;
type = get_value_type (parent->parent);
+ if (cfull_expression)
+ parent_expression = varobj_get_path_expr (parent->parent);
}
else
{
value = parent->value;
type = get_value_type (parent);
+ if (cfull_expression)
+ parent_expression = varobj_get_path_expr (parent);
}
- adjust_value_for_child_access (&value, &type);
+ adjust_value_for_child_access (&value, &type, &was_ptr);
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ || TYPE_CODE (type) == TYPE_CODE_UNION)
{
+ char *join = was_ptr ? "->" : ".";
if (CPLUS_FAKE_CHILD (parent))
{
/* The fields of the class type are ordered as they
@@ -2294,6 +2519,11 @@ cplus_describe_child (struct varobj *parent, int index,
if (ctype)
*ctype = TYPE_FIELD_TYPE (type, type_index);
+
+ if (cfull_expression)
+ *cfull_expression = xstrprintf ("((%s)%s%s)", parent_expression,
+ join,
+ TYPE_FIELD_NAME (type, type_index));
}
else if (index < TYPE_N_BASECLASSES (type))
{
@@ -2311,10 +2541,27 @@ cplus_describe_child (struct varobj *parent, int index,
{
*ctype = TYPE_FIELD_TYPE (type, index);
}
+
+ if (cfull_expression)
+ {
+ char *ptr = was_ptr ? "*" : "";
+ /* Cast the parent to the base' type. Note that in gdb,
+ expression like
+ (Base1)d
+ will create an lvalue, for all appearences, so we don't
+ need to use more fancy:
+ *(Base1*)(&d)
+ construct. */
+ *cfull_expression = xstrprintf ("(%s(%s%s) %s)",
+ ptr,
+ TYPE_FIELD_NAME (type, index),
+ ptr,
+ parent_expression);
+ }
}
else
{
- char *access = 0;
+ char *access = NULL;
int children[3];
cplus_class_num_children (type, children);
@@ -2353,16 +2600,17 @@ cplus_describe_child (struct varobj *parent, int index,
/* error! */
break;
}
-
+
+ gdb_assert (access);
if (cname)
*cname = xstrdup (access);
- /* Value and type are null here. */
+ /* Value and type and full expression are null here. */
}
}
else
{
- c_describe_child (parent, index, cname, cvalue, ctype);
+ c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression);
}
}
@@ -2370,10 +2618,18 @@ static char *
cplus_name_of_child (struct varobj *parent, int index)
{
char *name = NULL;
- cplus_describe_child (parent, index, &name, NULL, NULL);
+ cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
return name;
}
+static char *
+cplus_path_expr_of_child (struct varobj *child)
+{
+ cplus_describe_child (child->parent, child->index, NULL, NULL, NULL,
+ &child->path_expr);
+ return child->path_expr;
+}
+
static struct value *
cplus_value_of_root (struct varobj **var_handle)
{
@@ -2384,7 +2640,7 @@ static struct value *
cplus_value_of_child (struct varobj *parent, int index)
{
struct value *value = NULL;
- cplus_describe_child (parent, index, NULL, &value, NULL);
+ cplus_describe_child (parent, index, NULL, &value, NULL, NULL);
return value;
}
@@ -2392,21 +2648,12 @@ static struct type *
cplus_type_of_child (struct varobj *parent, int index)
{
struct type *type = NULL;
- cplus_describe_child (parent, index, NULL, NULL, &type);
+ cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
return type;
}
-static int
-cplus_variable_editable (struct varobj *var)
-{
- if (CPLUS_FAKE_CHILD (var))
- return 0;
-
- return c_variable_editable (var);
-}
-
static char *
-cplus_value_of_variable (struct varobj *var)
+cplus_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* If we have one of our special types, don't print out
@@ -2414,7 +2661,7 @@ cplus_value_of_variable (struct varobj *var)
if (CPLUS_FAKE_CHILD (var))
return xstrdup ("");
- return c_value_of_variable (var);
+ return c_value_of_variable (var, format);
}
/* Java */
@@ -2464,6 +2711,12 @@ java_name_of_child (struct varobj *parent, int index)
return name;
}
+static char *
+java_path_expr_of_child (struct varobj *child)
+{
+ return NULL;
+}
+
static struct value *
java_value_of_root (struct varobj **var_handle)
{
@@ -2482,16 +2735,10 @@ java_type_of_child (struct varobj *parent, int index)
return cplus_type_of_child (parent, index);
}
-static int
-java_variable_editable (struct varobj *var)
-{
- return cplus_variable_editable (var);
-}
-
static char *
-java_value_of_variable (struct varobj *var)
+java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
- return cplus_value_of_variable (var);
+ return cplus_value_of_variable (var, format);
}
extern void _initialize_varobj (void);
@@ -2512,3 +2759,49 @@ When non-zero, varobj debugging is enabled."),
show_varobjdebug,
&setlist, &showlist);
}
+
+/* Invalidate the varobjs that are tied to locals and re-create the ones that
+ are defined on globals.
+ Invalidated varobjs will be always printed in_scope="invalid". */
+void
+varobj_invalidate (void)
+{
+ struct varobj **all_rootvarobj;
+ struct varobj **varp;
+
+ if (varobj_list (&all_rootvarobj) > 0)
+ {
+ varp = all_rootvarobj;
+ while (*varp != NULL)
+ {
+ /* Floating varobjs are reparsed on each stop, so we don't care if
+ the presently parsed expression refers to something that's gone. */
+ if ((*varp)->root->floating)
+ continue;
+
+ /* global var must be re-evaluated. */
+ if ((*varp)->root->valid_block == NULL)
+ {
+ struct varobj *tmp_var;
+
+ /* Try to create a varobj with same expression. If we succeed replace
+ the old varobj, otherwise invalidate it. */
+ tmp_var = varobj_create (NULL, (*varp)->name, (CORE_ADDR) 0, USE_CURRENT_FRAME);
+ if (tmp_var != NULL)
+ {
+ tmp_var->obj_name = xstrdup ((*varp)->obj_name);
+ varobj_delete (*varp, NULL, 0);
+ install_variable (tmp_var);
+ }
+ else
+ (*varp)->root->is_valid = 0;
+ }
+ else /* locals must be invalidated. */
+ (*varp)->root->is_valid = 0;
+
+ varp++;
+ }
+ xfree (all_rootvarobj);
+ }
+ return;
+}