* varobj.h (varobj_set_frozen): New
(varobj_get_frozen): New.
(varobj_update): New parameter explicit.
* varobj.c (struct varobj): New fields frozen
and not_fetched.
(varobj_set_frozen, varobj_get_frozen): New.
(install_new_value): Don't fetch values for
frozen variable object, or children thereof. Allow
a frozen variable object to have non-fetched value.
(varobj_update): Allow updating child variables.
Don't traverse frozen children.
(new_variable): Initialize the frozen field.
(c_value_of_variable): Return NULL for frozen
variable without any value yet.
* mi/mi-cmd-var.c (varobj_update_one): New parameter
'explicit'.
(mi_cmd_var_create): Output the 'frozen' field,
as soon as testsuite is adjusted to expect that field.
(mi_cmd_var_set_frozen): New.
(mi_cmd_var_update): Pass the 'explicit' parameter to
varobj_update_one.
* mi/mi-cmds.c (mi_cmds): Register '-var-set-frozen'.
* mi/mi-cmds.h (mi_cmd_var_set_frozen): Declare.
This commit is contained in:
parent
4d115fc687
commit
25d5ea921b
@ -1,3 +1,29 @@
|
||||
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* varobj.h (varobj_set_frozen): New
|
||||
(varobj_get_frozen): New.
|
||||
(varobj_update): New parameter explicit.
|
||||
* varobj.c (struct varobj): New fields frozen
|
||||
and not_fetched.
|
||||
(varobj_set_frozen, varobj_get_frozen): New.
|
||||
(install_new_value): Don't fetch values for
|
||||
frozen variable object, or children thereof. Allow
|
||||
a frozen variable object to have non-fetched value.
|
||||
(varobj_update): Allow updating child variables.
|
||||
Don't traverse frozen children.
|
||||
(new_variable): Initialize the frozen field.
|
||||
(c_value_of_variable): Return NULL for frozen
|
||||
variable without any value yet.
|
||||
* mi/mi-cmd-var.c (varobj_update_one): New parameter
|
||||
'explicit'.
|
||||
(mi_cmd_var_create): Output the 'frozen' field,
|
||||
as soon as testsuite is adjusted to expect that field.
|
||||
(mi_cmd_var_set_frozen): New.
|
||||
(mi_cmd_var_update): Pass the 'explicit' parameter to
|
||||
varobj_update_one.
|
||||
* mi/mi-cmds.c (mi_cmds): Register '-var-set-frozen'.
|
||||
* mi/mi-cmds.h (mi_cmd_var_set_frozen): Declare.
|
||||
|
||||
2007-04-13 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* target-descriptions.c (tdesc_named_type): Add ieee_single and
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (GDB/MI Variable Objects): Document
|
||||
frozen variables objects.
|
||||
|
||||
2007-04-13 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Memory): Reference Remote Debugging chapter.
|
||||
|
||||
@ -17296,7 +17296,7 @@ New fields may be added to the output of any MI command.
|
||||
|
||||
@item
|
||||
The range of values for fields with specified values, e.g.,
|
||||
@code{in_scope} (@pxref{-var-update}) may be extended.
|
||||
@code{in_scope} (@pxref{-var-update-fields}) may be extended.
|
||||
|
||||
@c The format of field's content e.g type prefix, may change so parse it
|
||||
@c at your own risk. Yes, in general?
|
||||
@ -19223,7 +19223,10 @@ that corresponds to a composite type, such as structure in C, has
|
||||
a number of child variable objects, for example corresponding to each
|
||||
element of a structure. A child variable object can itself have
|
||||
children, recursively. Recursion ends when we reach
|
||||
leaf variable objects, which always have built-in types.
|
||||
leaf variable objects, which always have built-in types. Child variable
|
||||
objects are created only by explicit request, so if a frontend
|
||||
is not interested in the children of a particular variable object, no
|
||||
child will be created.
|
||||
|
||||
For a leaf variable object it is possible to obtain its value as a
|
||||
string, or set the value from a string. String value can be also
|
||||
@ -19235,7 +19238,19 @@ A frontend does not need to read the values of all variable objects each time
|
||||
the program stops. Instead, MI provides an update command that lists all
|
||||
variable objects whose values has changed since the last update
|
||||
operation. This considerably reduces the amount of data that must
|
||||
be transferred to the frontend.
|
||||
be transferred to the frontend. As noted above, children variable
|
||||
objects are created on demand, and only leaf variable objects have a
|
||||
real value. As result, gdb will read target memory only for leaf
|
||||
variables that frontend has created.
|
||||
|
||||
The automatic update is not always desirable. For example, a frontend
|
||||
might want to keep a value of some expression for future reference,
|
||||
and never update it. For another example, fetching memory is
|
||||
relatively slow for embedded targets, so a frontend might want
|
||||
to disable automatic update for the variables that are either not
|
||||
visible on the screen, or ``closed''. This is possible using so
|
||||
called ``frozen variable objects''. Such variable objects are never
|
||||
implicitly updated.
|
||||
|
||||
The following is the complete set of @sc{gdb/mi} operations defined to
|
||||
access this functionality:
|
||||
@ -19268,6 +19283,8 @@ access this functionality:
|
||||
@tab set the value of this variable
|
||||
@item @code{-var-update}
|
||||
@tab update the variable and its children
|
||||
@item @code{-var-set-frozen}
|
||||
@tab set frozeness attribute
|
||||
@end multitable
|
||||
|
||||
In the next subsection we describe each operation in detail and suggest
|
||||
@ -19533,6 +19550,7 @@ subsequent @code{-var-update} list.
|
||||
|
||||
@subheading The @code{-var-update} Command
|
||||
@findex -var-update
|
||||
@anchor{-var-update}
|
||||
|
||||
@subsubheading Synopsis
|
||||
|
||||
@ -19567,7 +19585,7 @@ type_changed="false"@}]
|
||||
(gdb)
|
||||
@end smallexample
|
||||
|
||||
@anchor{-var-update}
|
||||
@anchor{-var-update-fields}
|
||||
The field in_scope may take three values:
|
||||
|
||||
@table @code
|
||||
@ -19590,6 +19608,37 @@ objects.
|
||||
In the future new values may be added to this list so the front should
|
||||
be prepared for this possibility. @xref{GDB/MI Development and Front Ends, ,@sc{GDB/MI} Development and Front Ends}.
|
||||
|
||||
@subheading The @code{-var-set-frozen} Command
|
||||
@findex -var-set-frozen
|
||||
|
||||
@subsubheading Synopsis
|
||||
|
||||
@smallexample
|
||||
-var-set-frozen @var{name} @samp{flag}
|
||||
@end smallexample
|
||||
|
||||
Set the frozeness flag on the variable object @var{name}. The
|
||||
@var{flag} parameter should be either @samp{1} to make the variable
|
||||
frozen or @samp{0} to make it unfozen. If a variable object is
|
||||
frozen, then neither itself, nor any of its children, are
|
||||
implicitly updated by @code{-var-update} (@pxref{-var-update}) of
|
||||
a parent variable or by @code{-var-update *}. Only
|
||||
@code{-var-update} of the variable itself will update its value and
|
||||
values of its children. After a variable object is unfrozen, it is
|
||||
implicitly updated by all subsequent @code{-var-update} operations.
|
||||
Unfreezing a variable does not update it, only subsequent
|
||||
@code{-var-update} does.
|
||||
|
||||
@subsubheading Example
|
||||
|
||||
@smallexample
|
||||
(gdb)
|
||||
-var-set-frozen V 1
|
||||
^done
|
||||
(gdb)
|
||||
@end smallexample
|
||||
|
||||
|
||||
@c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
@node GDB/MI Data Manipulation
|
||||
@section @sc{gdb/mi} Data Manipulation
|
||||
|
||||
@ -37,7 +37,8 @@ const char mi_all_values[] = "--all-values";
|
||||
extern int varobjdebug; /* defined in varobj.c. */
|
||||
|
||||
static void varobj_update_one (struct varobj *var,
|
||||
enum print_values print_values);
|
||||
enum print_values print_values,
|
||||
int explicit);
|
||||
|
||||
static int mi_print_value_p (struct type *type, enum print_values print_values);
|
||||
|
||||
@ -64,6 +65,9 @@ print_varobj (struct varobj *var, enum print_values print_values,
|
||||
ui_out_field_string (uiout, "type", type);
|
||||
xfree (type);
|
||||
}
|
||||
|
||||
if (varobj_get_frozen (var))
|
||||
ui_out_field_int (uiout, "frozen", 1);
|
||||
}
|
||||
|
||||
/* VAROBJ operations */
|
||||
@ -232,6 +236,35 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
|
||||
return MI_CMD_DONE;
|
||||
}
|
||||
|
||||
enum mi_cmd_result
|
||||
mi_cmd_var_set_frozen (char *command, char **argv, int argc)
|
||||
{
|
||||
struct varobj *var;
|
||||
int frozen;
|
||||
|
||||
if (argc != 2)
|
||||
error (_("-var-set-format: Usage: NAME FROZEN_FLAG."));
|
||||
|
||||
var = varobj_get_handle (argv[0]);
|
||||
if (var == NULL)
|
||||
error (_("Variable object not found"));
|
||||
|
||||
if (strcmp (argv[1], "0") == 0)
|
||||
frozen = 0;
|
||||
else if (strcmp (argv[1], "1") == 0)
|
||||
frozen = 1;
|
||||
else
|
||||
error (_("Invalid flag value"));
|
||||
|
||||
varobj_set_frozen (var, frozen);
|
||||
|
||||
/* We don't automatically return the new value, or what varobjs got new
|
||||
values during unfreezing. If this information is required, client
|
||||
should call -var-update explicitly. */
|
||||
return MI_CMD_DONE;
|
||||
}
|
||||
|
||||
|
||||
enum mi_cmd_result
|
||||
mi_cmd_var_show_format (char *command, char **argv, int argc)
|
||||
{
|
||||
@ -513,7 +546,7 @@ mi_cmd_var_update (char *command, char **argv, int argc)
|
||||
cr = rootlist;
|
||||
while (*cr != NULL)
|
||||
{
|
||||
varobj_update_one (*cr, print_values);
|
||||
varobj_update_one (*cr, print_values, 0 /* implicit */);
|
||||
cr++;
|
||||
}
|
||||
do_cleanups (cleanup);
|
||||
@ -529,7 +562,7 @@ mi_cmd_var_update (char *command, char **argv, int argc)
|
||||
cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "changelist");
|
||||
else
|
||||
cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changelist");
|
||||
varobj_update_one (var, print_values);
|
||||
varobj_update_one (var, print_values, 1 /* explicit */);
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
return MI_CMD_DONE;
|
||||
@ -538,14 +571,15 @@ mi_cmd_var_update (char *command, char **argv, int argc)
|
||||
/* Helper for mi_cmd_var_update(). */
|
||||
|
||||
static void
|
||||
varobj_update_one (struct varobj *var, enum print_values print_values)
|
||||
varobj_update_one (struct varobj *var, enum print_values print_values,
|
||||
int explicit)
|
||||
{
|
||||
struct varobj **changelist;
|
||||
struct varobj **cc;
|
||||
struct cleanup *cleanup = NULL;
|
||||
int nc;
|
||||
|
||||
nc = varobj_update (&var, &changelist);
|
||||
nc = varobj_update (&var, &changelist, explicit);
|
||||
|
||||
/* nc >= 0 represents the number of changes reported into changelist.
|
||||
nc < 0 means that an error occured or the the variable has
|
||||
|
||||
@ -156,6 +156,7 @@ struct mi_cmd mi_cmds[] =
|
||||
{ "var-info-type", { NULL, 0 }, 0, mi_cmd_var_info_type},
|
||||
{ "var-list-children", { NULL, 0 }, 0, mi_cmd_var_list_children},
|
||||
{ "var-set-format", { NULL, 0 }, 0, mi_cmd_var_set_format},
|
||||
{ "var-set-frozen", { NULL, 0 }, 0, mi_cmd_var_set_frozen},
|
||||
{ "var-show-attributes", { NULL, 0 }, 0, mi_cmd_var_show_attributes},
|
||||
{ "var-show-format", { NULL, 0 }, 0, mi_cmd_var_show_format},
|
||||
{ "var-update", { NULL, 0 }, 0, mi_cmd_var_update},
|
||||
|
||||
@ -113,6 +113,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_info_num_children;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_info_type;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_list_children;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_set_format;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_set_frozen;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_show_attributes;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_show_format;
|
||||
extern mi_cmd_argv_ftype mi_cmd_var_update;
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* gdb.mi/mi-var-cmd.exp: Delete varobjs left by previous
|
||||
tests. Run the frozen varobjs test.
|
||||
* gdb.mi/var-cmd.c (do_frozen_tests): New.
|
||||
* lib/mi-support.exp (mi_varobj_update): Fix thinko.
|
||||
|
||||
2007-04-11 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/type-opaque-lib.c, gdb.base/type-opaque-main.c,
|
||||
|
||||
@ -596,6 +596,20 @@ mi_gdb_test "-var-update selected_a" \
|
||||
"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
|
||||
"update selected_a in do_special_tests"
|
||||
|
||||
mi_delete_varobj selected_a "delete selected_a"
|
||||
mi_delete_varobj array_ptr "delete array_ptr"
|
||||
|
||||
proc set_frozen {varobjs flag} {
|
||||
foreach v $varobjs {
|
||||
mi_gdb_test "-var-set-frozen $v $flag" \
|
||||
"\\^done" \
|
||||
"-var-set-frozen $v $flag"
|
||||
}
|
||||
}
|
||||
|
||||
mi_prepare_inline_tests $srcfile
|
||||
mi_run_inline_test frozen
|
||||
|
||||
# Test whether bad varobjs crash GDB.
|
||||
|
||||
# A varobj we fail to read during -var-update should be considered
|
||||
|
||||
@ -315,6 +315,92 @@ do_special_tests (void)
|
||||
incr_a(2);
|
||||
}
|
||||
|
||||
void do_frozen_tests ()
|
||||
{
|
||||
/*: BEGIN: frozen :*/
|
||||
struct {
|
||||
int i;
|
||||
struct {
|
||||
int j;
|
||||
int k;
|
||||
} nested;
|
||||
} v1 = {1, {2, 3}};
|
||||
|
||||
int v2 = 4;
|
||||
/*:
|
||||
mi_create_varobj V1 v1 "create varobj for v1"
|
||||
mi_create_varobj V2 v2 "create varobj for v2"
|
||||
|
||||
mi_list_varobj_children "V1" {
|
||||
{"V1.i" "i" "0" "int"}
|
||||
{"V1.nested" "nested" "2" "struct {...}"}
|
||||
} "list children of v1"
|
||||
|
||||
mi_list_varobj_children "V1.nested" {
|
||||
{"V1.nested.j" "j" "0" "int"}
|
||||
{"V1.nested.k" "k" "0" "int"}
|
||||
} "list children of v1.nested"
|
||||
|
||||
mi_check_varobj_value V1.i 1 "check V1.i: 1"
|
||||
mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
|
||||
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
|
||||
mi_check_varobj_value V2 4 "check V2: 4"
|
||||
:*/
|
||||
v2 = 5;
|
||||
/*:
|
||||
mi_varobj_update * {V2} "update varobjs: V2 changed"
|
||||
set_frozen V2 1
|
||||
:*/
|
||||
v2 = 6;
|
||||
/*:
|
||||
mi_varobj_update * {} "update varobjs: nothing changed"
|
||||
mi_check_varobj_value V2 5 "check V2: 5"
|
||||
mi_varobj_update V2 {V2} "update V2 explicitly"
|
||||
mi_check_varobj_value V2 6 "check V2: 6"
|
||||
:*/
|
||||
v1.i = 7;
|
||||
v1.nested.j = 8;
|
||||
v1.nested.k = 9;
|
||||
/*:
|
||||
set_frozen V1 1
|
||||
mi_varobj_update * {} "update varobjs: nothing changed"
|
||||
mi_check_varobj_value V1.i 1 "check V1.i: 1"
|
||||
mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
|
||||
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
|
||||
# Check that explicit update for elements of structures
|
||||
# works.
|
||||
# Update v1.j
|
||||
mi_varobj_update V1.nested.j {V1.nested.j} "update V1.nested.j"
|
||||
mi_check_varobj_value V1.i 1 "check V1.i: 1"
|
||||
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
|
||||
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
|
||||
# Update v1.nested, check that children is updated.
|
||||
mi_varobj_update V1.nested {V1.nested.k} "update V1.nested"
|
||||
mi_check_varobj_value V1.i 1 "check V1.i: 1"
|
||||
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
|
||||
mi_check_varobj_value V1.nested.k 9 "check V1.nested.k: 9"
|
||||
# Update v1.i
|
||||
mi_varobj_update V1.i {V1.i} "update V1.i"
|
||||
mi_check_varobj_value V1.i 7 "check V1.i: 7"
|
||||
:*/
|
||||
v1.i = 10;
|
||||
v1.nested.j = 11;
|
||||
v1.nested.k = 12;
|
||||
/*:
|
||||
# Check that unfreeze itself does not updates the values.
|
||||
set_frozen V1 0
|
||||
mi_check_varobj_value V1.i 7 "check V1.i: 7"
|
||||
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
|
||||
mi_check_varobj_value V1.nested.k 9 "check V1.nested.k: 9"
|
||||
mi_varobj_update V1 {V1.i V1.nested.j V1.nested.k} "update V1"
|
||||
mi_check_varobj_value V1.i 10 "check V1.i: 10"
|
||||
mi_check_varobj_value V1.nested.j 11 "check V1.nested.j: 11"
|
||||
mi_check_varobj_value V1.nested.k 12 "check V1.nested.k: 12"
|
||||
:*/
|
||||
|
||||
/*: END: frozen :*/
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{
|
||||
@ -322,6 +408,7 @@ main (int argc, char *argv [])
|
||||
do_block_tests ();
|
||||
do_children_tests ();
|
||||
do_special_tests ();
|
||||
do_frozen_tests ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
@ -1024,8 +1024,9 @@ proc mi_varobj_update { name expected testname } {
|
||||
set first 1
|
||||
foreach item $expected {
|
||||
set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}"
|
||||
if {$first} {
|
||||
if {$first == 1} {
|
||||
set er "$er$v"
|
||||
set first 0
|
||||
} else {
|
||||
set er "$er,$v"
|
||||
}
|
||||
@ -1312,7 +1313,7 @@ proc mi_run_inline_test { testcase } {
|
||||
set line_now [mi_wait_for_stop "$testcase: step to $line"]
|
||||
set first 0
|
||||
} elseif {$line_now!=$line} {
|
||||
set line_now [mi_continue_to_line "$mi_autotest_source:$line"]
|
||||
set line_now [mi_continue_to_line "$mi_autotest_source:$line" "continue to $line"]
|
||||
}
|
||||
|
||||
if {$line_now!=$line} {
|
||||
|
||||
167
gdb/varobj.c
167
gdb/varobj.c
@ -137,6 +137,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 <direct-or-indirect-parent>. */
|
||||
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
|
||||
@ -669,6 +679,26 @@ varobj_get_display_format (struct varobj *var)
|
||||
return var->format;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -915,6 +945,7 @@ 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;
|
||||
|
||||
/* 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
|
||||
@ -950,7 +981,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,
|
||||
@ -980,9 +1024,16 @@ install_new_value (struct varobj *var, struct value *value, int initial)
|
||||
{
|
||||
/* 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)
|
||||
@ -1012,9 +1063,13 @@ install_new_value (struct varobj *var, struct value *value, int initial)
|
||||
}
|
||||
|
||||
/* 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 (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));
|
||||
@ -1031,17 +1086,21 @@ install_new_value (struct varobj *var, struct value *value, int initial)
|
||||
< 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 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 type_changed;
|
||||
int type_changed = 0;
|
||||
int i;
|
||||
int vleft;
|
||||
struct varobj *v;
|
||||
@ -1056,48 +1115,56 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
|
||||
/* sanity check: have we been passed a pointer? */
|
||||
gdb_assert (changelist);
|
||||
|
||||
if (!is_root_p (*varp))
|
||||
error (_("Only root variables can be updated"));
|
||||
/* 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 (!(*varp)->root->is_valid)
|
||||
return INVALID;
|
||||
|
||||
/* Save the selected stack frame, since we will need to change it
|
||||
in order to evaluate expressions. */
|
||||
old_fid = get_frame_id (deprecated_safe_get_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);
|
||||
|
||||
/* 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 (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);
|
||||
}
|
||||
/* Save the selected stack frame, since we will need to change it
|
||||
in order to evaluate expressions. */
|
||||
old_fid = get_frame_id (deprecated_safe_get_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);
|
||||
|
||||
if (new == NULL)
|
||||
{
|
||||
/* This means the varobj itself is out of scope.
|
||||
Report it. */
|
||||
VEC_free (varobj_p, result);
|
||||
return NOT_IN_SCOPE;
|
||||
/* Restore selected frame. */
|
||||
fi = frame_find_by_id (old_fid);
|
||||
if (fi)
|
||||
select_frame (fi);
|
||||
|
||||
/* 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 (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 NOT_IN_SCOPE;
|
||||
}
|
||||
}
|
||||
|
||||
VEC_safe_push (varobj_p, stack, *varp);
|
||||
@ -1115,13 +1182,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 */))
|
||||
@ -1403,6 +1470,8 @@ new_variable (void)
|
||||
var->root = NULL;
|
||||
var->updated = 0;
|
||||
var->print_value = NULL;
|
||||
var->frozen = 0;
|
||||
var->not_fetched = 0;
|
||||
|
||||
return var;
|
||||
}
|
||||
@ -2116,6 +2185,12 @@ 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);
|
||||
|
||||
@ -86,6 +86,10 @@ extern enum varobj_display_formats varobj_set_display_format (
|
||||
extern enum varobj_display_formats varobj_get_display_format (
|
||||
struct varobj *var);
|
||||
|
||||
extern void varobj_set_frozen (struct varobj *var, int frozen);
|
||||
|
||||
extern int varobj_get_frozen (struct varobj *var);
|
||||
|
||||
extern int varobj_get_num_children (struct varobj *var);
|
||||
|
||||
extern int varobj_list_children (struct varobj *var,
|
||||
@ -105,7 +109,8 @@ extern int varobj_set_value (struct varobj *var, char *expression);
|
||||
|
||||
extern int varobj_list (struct varobj ***rootlist);
|
||||
|
||||
extern int varobj_update (struct varobj **varp, struct varobj ***changelist);
|
||||
extern int varobj_update (struct varobj **varp, struct varobj ***changelist,
|
||||
int explicit);
|
||||
|
||||
extern void varobj_invalidate (void);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user