| Index: gdb/varobj.c
|
| diff --git a/gdb/varobj.c b/gdb/varobj.c
|
| index 195d8214167e74f22ca35d2b61e50f177059ef50..6b7ec52c983d1e63fb3b4897f152abba06119409 100644
|
| --- a/gdb/varobj.c
|
| +++ b/gdb/varobj.c
|
| @@ -21,7 +21,6 @@
|
| #include "expression.h"
|
| #include "frame.h"
|
| #include "language.h"
|
| -#include "wrapper.h"
|
| #include "gdbcmd.h"
|
| #include "block.h"
|
| #include "valprint.h"
|
| @@ -34,6 +33,8 @@
|
| #include "vec.h"
|
| #include "gdbthread.h"
|
| #include "inferior.h"
|
| +#include "ada-varobj.h"
|
| +#include "ada-lang.h"
|
|
|
| #if HAVE_PYTHON
|
| #include "python/python.h"
|
| @@ -42,6 +43,10 @@
|
| typedef int PyObject;
|
| #endif
|
|
|
| +/* The names of varobjs representing anonymous structs or unions. */
|
| +#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>")
|
| +#define ANONYMOUS_UNION_NAME _("<anonymous union>")
|
| +
|
| /* Non-zero if we want to see trace of varobj level stuff. */
|
|
|
| int varobjdebug = 0;
|
| @@ -265,6 +270,9 @@ static void cppush (struct cpstack **pstack, char *name);
|
|
|
| static char *cppop (struct cpstack **pstack);
|
|
|
| +static int update_type_if_necessary (struct varobj *var,
|
| + struct value *new_value);
|
| +
|
| static int install_new_value (struct varobj *var, struct value *value,
|
| int initial);
|
|
|
| @@ -301,6 +309,8 @@ static struct varobj *varobj_add_child (struct varobj *var,
|
|
|
| #endif /* HAVE_PYTHON */
|
|
|
| +static int default_value_is_changeable_p (struct varobj *var);
|
| +
|
| /* C implementation */
|
|
|
| static int c_number_of_children (struct varobj *var);
|
| @@ -379,6 +389,11 @@ 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_is_changeable_p (struct varobj *var);
|
| +
|
| +static int ada_value_has_mutated (struct varobj *var, struct value *new_val,
|
| + struct type *new_type);
|
| +
|
| /* The language specific vector */
|
|
|
| struct language_specific
|
| @@ -412,6 +427,31 @@ struct language_specific
|
| /* The current value of VAR. */
|
| char *(*value_of_variable) (struct varobj * var,
|
| enum varobj_display_formats format);
|
| +
|
| + /* Return non-zero if changes in value of VAR must be detected and
|
| + reported by -var-update. Return zero if -var-update should never
|
| + report changes of such values. This makes sense for structures
|
| + (since the changes in children values will be reported separately),
|
| + or for artifical objects (like 'public' pseudo-field in C++).
|
| +
|
| + Return value of 0 means that gdb need not call value_fetch_lazy
|
| + for the value of this variable object. */
|
| + int (*value_is_changeable_p) (struct varobj *var);
|
| +
|
| + /* 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. */
|
| @@ -426,7 +466,9 @@ 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,
|
| + default_value_is_changeable_p,
|
| + NULL /* value_has_mutated */}
|
| ,
|
| /* C */
|
| {
|
| @@ -438,7 +480,9 @@ 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,
|
| + default_value_is_changeable_p,
|
| + NULL /* value_has_mutated */}
|
| ,
|
| /* C++ */
|
| {
|
| @@ -450,7 +494,9 @@ 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,
|
| + default_value_is_changeable_p,
|
| + NULL /* value_has_mutated */}
|
| ,
|
| /* Java */
|
| {
|
| @@ -462,7 +508,9 @@ 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,
|
| + default_value_is_changeable_p,
|
| + NULL /* value_has_mutated */},
|
| /* Ada */
|
| {
|
| vlang_ada,
|
| @@ -473,7 +521,9 @@ 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_is_changeable_p,
|
| + ada_value_has_mutated}
|
| };
|
|
|
| /* A little convenience enum for dealing with C++/Java. */
|
| @@ -512,7 +562,7 @@ is_root_p (struct varobj *var)
|
| #ifdef HAVE_PYTHON
|
| /* Helper function to install a Python environment suitable for
|
| use during operations on VAR. */
|
| -struct cleanup *
|
| +static struct cleanup *
|
| varobj_ensure_python_env (struct varobj *var)
|
| {
|
| return ensure_python_env (var->root->exp->gdbarch,
|
| @@ -573,6 +623,8 @@ varobj_create (char *objname,
|
| char *p;
|
| enum varobj_languages lang;
|
| struct value *value = NULL;
|
| + volatile struct gdb_exception except;
|
| + CORE_ADDR pc;
|
|
|
| /* Parse and evaluate the expression, filling in as much of the
|
| variable's data as possible. */
|
| @@ -599,15 +651,24 @@ varobj_create (char *objname,
|
| if (type == USE_SELECTED_FRAME)
|
| var->root->floating = 1;
|
|
|
| + pc = 0;
|
| block = NULL;
|
| if (fi != NULL)
|
| - block = get_frame_block (fi, 0);
|
| + {
|
| + block = get_frame_block (fi, 0);
|
| + pc = get_frame_pc (fi);
|
| + }
|
|
|
| p = expression;
|
| innermost_block = NULL;
|
| /* Wrap the call to parse expression, so we can
|
| return a sensible error. */
|
| - if (!gdb_parse_exp_1 (&p, block, 0, &var->root->exp))
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + var->root->exp = parse_exp_1 (&p, pc, block, 0);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| {
|
| do_cleanups (old_chain);
|
| return NULL;
|
| @@ -650,7 +711,12 @@ varobj_create (char *objname,
|
| /* 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))
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + value = evaluate_expression (var->root->exp);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| {
|
| /* Error getting the value. Try to at least get the
|
| right type. */
|
| @@ -658,15 +724,21 @@ varobj_create (char *objname,
|
|
|
| var->type = value_type (type_only_value);
|
| }
|
| - else
|
| - var->type = value_type (value);
|
| + else
|
| + {
|
| + int real_type_found = 0;
|
|
|
| - install_new_value (var, value, 1 /* Initial assignment */);
|
| + var->type = value_actual_type (value, 0, &real_type_found);
|
| + if (real_type_found)
|
| + value = value_cast (var->type, value);
|
| + }
|
|
|
| /* Set language info */
|
| lang = variable_language (var);
|
| var->root->lang = &languages[lang];
|
|
|
| + install_new_value (var, value, 1 /* Initial assignment */);
|
| +
|
| /* Set ourselves as our root. */
|
| var->root->rootvar = var;
|
|
|
| @@ -947,6 +1019,7 @@ restrict_range (VEC (varobj_p) *children, int *from, int *to)
|
| static void
|
| install_dynamic_child (struct varobj *var,
|
| VEC (varobj_p) **changed,
|
| + VEC (varobj_p) **type_changed,
|
| VEC (varobj_p) **new,
|
| VEC (varobj_p) **unchanged,
|
| int *cchanged,
|
| @@ -969,12 +1042,18 @@ install_dynamic_child (struct varobj *var,
|
| {
|
| varobj_p existing = VEC_index (varobj_p, var->children, index);
|
|
|
| + int type_updated = update_type_if_necessary (existing, value);
|
| + if (type_updated)
|
| + {
|
| + if (type_changed)
|
| + VEC_safe_push (varobj_p, *type_changed, existing);
|
| + }
|
| if (install_new_value (existing, value, 0))
|
| {
|
| - if (changed)
|
| + if (!type_updated && changed)
|
| VEC_safe_push (varobj_p, *changed, existing);
|
| }
|
| - else if (unchanged)
|
| + else if (!type_updated && unchanged)
|
| VEC_safe_push (varobj_p, *unchanged, existing);
|
| }
|
| }
|
| @@ -997,6 +1076,7 @@ dynamic_varobj_has_child_method (struct varobj *var)
|
| static int
|
| update_dynamic_varobj_children (struct varobj *var,
|
| VEC (varobj_p) **changed,
|
| + VEC (varobj_p) **type_changed,
|
| VEC (varobj_p) **new,
|
| VEC (varobj_p) **unchanged,
|
| int *cchanged,
|
| @@ -1032,9 +1112,6 @@ update_dynamic_varobj_children (struct varobj *var,
|
|
|
| make_cleanup_py_decref (children);
|
|
|
| - if (!PyIter_Check (children))
|
| - error (_("Returned value is not iterable"));
|
| -
|
| Py_XDECREF (var->child_iter);
|
| var->child_iter = PyObject_GetIter (children);
|
| if (!var->child_iter)
|
| @@ -1132,6 +1209,7 @@ update_dynamic_varobj_children (struct varobj *var,
|
| if (v == NULL)
|
| gdbpy_print_stack ();
|
| install_dynamic_child (var, can_mention ? changed : NULL,
|
| + can_mention ? type_changed : NULL,
|
| can_mention ? new : NULL,
|
| can_mention ? unchanged : NULL,
|
| can_mention ? cchanged : NULL, i, name, v);
|
| @@ -1187,7 +1265,7 @@ varobj_get_num_children (struct varobj *var)
|
|
|
| /* If we have a dynamic varobj, don't report -1 children.
|
| So, try to fetch some children first. */
|
| - update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy,
|
| + update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL, &dummy,
|
| 0, 0, 0);
|
| }
|
| else
|
| @@ -1213,8 +1291,8 @@ varobj_list_children (struct varobj *var, int *from, int *to)
|
| /* This, in theory, can result in the number of children changing without
|
| frontend noticing. But well, calling -var-list-children on the same
|
| varobj twice is not something a sane frontend would do. */
|
| - update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed,
|
| - 0, 0, *to);
|
| + update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL,
|
| + &children_changed, 0, 0, *to);
|
| restrict_range (var->children, from, to);
|
| return var->children;
|
| }
|
| @@ -1288,6 +1366,39 @@ varobj_get_gdb_type (struct varobj *var)
|
| return var->type;
|
| }
|
|
|
| +/* Is VAR a path expression parent, i.e., can it be used to construct
|
| + a valid path expression? */
|
| +
|
| +static int
|
| +is_path_expr_parent (struct varobj *var)
|
| +{
|
| + struct type *type;
|
| +
|
| + /* "Fake" children are not path_expr parents. */
|
| + if (CPLUS_FAKE_CHILD (var))
|
| + return 0;
|
| +
|
| + type = get_value_type (var);
|
| +
|
| + /* Anonymous unions and structs are also not path_expr parents. */
|
| + return !((TYPE_CODE (type) == TYPE_CODE_STRUCT
|
| + || TYPE_CODE (type) == TYPE_CODE_UNION)
|
| + && TYPE_NAME (type) == NULL);
|
| +}
|
| +
|
| +/* Return the path expression parent for VAR. */
|
| +
|
| +static struct varobj *
|
| +get_path_expr_parent (struct varobj *var)
|
| +{
|
| + struct varobj *parent = var;
|
| +
|
| + while (!is_root_p (parent) && !is_path_expr_parent (parent))
|
| + parent = parent->parent;
|
| +
|
| + return parent;
|
| +}
|
| +
|
| /* Return a pointer to the full rooted expression of varobj VAR.
|
| If it has not been computed yet, compute it. */
|
| char *
|
| @@ -1349,21 +1460,26 @@ varobj_get_value (struct varobj *var)
|
| int
|
| varobj_set_value (struct varobj *var, char *expression)
|
| {
|
| - struct value *val;
|
| -
|
| + struct value *val = NULL; /* Initialize to keep gcc happy. */
|
| /* The argument "expression" contains the variable's new value.
|
| We need to first construct a legal expression for this -- ugh! */
|
| /* Does this cover all the bases? */
|
| struct expression *exp;
|
| - struct value *value;
|
| + struct value *value = NULL; /* Initialize to keep gcc happy. */
|
| int saved_input_radix = input_radix;
|
| char *s = expression;
|
| + volatile struct gdb_exception except;
|
|
|
| gdb_assert (varobj_editable_p (var));
|
|
|
| input_radix = 10; /* ALWAYS reset to decimal temporarily. */
|
| - exp = parse_exp_1 (&s, 0, 0);
|
| - if (!gdb_evaluate_expression (exp, &value))
|
| + exp = parse_exp_1 (&s, 0, 0, 0);
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + value = evaluate_expression (exp);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| {
|
| /* We cannot proceed without a valid expression. */
|
| xfree (exp);
|
| @@ -1385,13 +1501,16 @@ varobj_set_value (struct varobj *var, char *expression)
|
| 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))
|
| + /* The new value may be lazy. value_assign, or
|
| + rather value_contents, will take care of this. */
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + val = value_assign (var->value, value);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| 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
|
| @@ -1520,6 +1639,43 @@ install_new_value_visualizer (struct varobj *var)
|
| #endif
|
| }
|
|
|
| +/* When using RTTI to determine variable type it may be changed in runtime when
|
| + the variable value is changed. This function checks whether type of varobj
|
| + VAR will change when a new value NEW_VALUE is assigned and if it is so
|
| + updates the type of VAR. */
|
| +
|
| +static int
|
| +update_type_if_necessary (struct varobj *var, struct value *new_value)
|
| +{
|
| + if (new_value)
|
| + {
|
| + struct value_print_options opts;
|
| +
|
| + get_user_print_options (&opts);
|
| + if (opts.objectprint)
|
| + {
|
| + struct type *new_type;
|
| + char *curr_type_str, *new_type_str;
|
| +
|
| + new_type = value_actual_type (new_value, 0, 0);
|
| + new_type_str = type_to_string (new_type);
|
| + curr_type_str = varobj_get_type (var);
|
| + if (strcmp (curr_type_str, new_type_str) != 0)
|
| + {
|
| + var->type = new_type;
|
| +
|
| + /* This information may be not valid for a new type. */
|
| + varobj_delete (var, NULL, 1);
|
| + VEC_free (varobj_p, var->children);
|
| + var->num_children = -1;
|
| + return 1;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| /* Assign a new value to a variable object. If INITIAL is non-zero,
|
| this is the first assignement after the variable object was just
|
| created, or changed type. In that case, just assign the value
|
| @@ -1594,15 +1750,29 @@ install_new_value (struct varobj *var, struct value *value, int initial)
|
| explicitly asked to compare the new value with the old one. */
|
| intentionally_not_fetched = 1;
|
| }
|
| - else if (!gdb_value_fetch_lazy (value))
|
| + else
|
| {
|
| - /* Set the value to NULL, so that for the next -var-update,
|
| - we don't try to compare the new value with this value,
|
| - that we couldn't even read. */
|
| - value = NULL;
|
| + volatile struct gdb_exception except;
|
| +
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + value_fetch_lazy (value);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| + {
|
| + /* Set the value to NULL, so that for the next -var-update,
|
| + we don't try to compare the new value with this value,
|
| + that we couldn't even read. */
|
| + value = NULL;
|
| + }
|
| }
|
| }
|
|
|
| + /* Get a reference now, before possibly passing it to any Python
|
| + code that might release it. */
|
| + if (value != NULL)
|
| + value_incref (value);
|
|
|
| /* Below, we'll be comparing string rendering of old and new
|
| values. Don't get string rendering if the value is
|
| @@ -1670,8 +1840,6 @@ install_new_value (struct varobj *var, struct value *value, int initial)
|
| if (var->value != NULL && var->value != value)
|
| value_free (var->value);
|
| var->value = value;
|
| - if (value != NULL)
|
| - value_incref (value);
|
| if (value && value_lazy (value) && intentionally_not_fetched)
|
| var->not_fetched = 1;
|
| else
|
| @@ -1757,6 +1925,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
|
| @@ -1772,7 +1964,8 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
|
| returns TYPE_CHANGED, then it has done this and VARP will be modified
|
| to point to the new varobj. */
|
|
|
| -VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| +VEC(varobj_update_result) *
|
| +varobj_update (struct varobj **varp, int explicit)
|
| {
|
| int changed = 0;
|
| int type_changed = 0;
|
| @@ -1812,8 +2005,9 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| value_of_root variable dispose of the varobj if the type
|
| has changed. */
|
| new = value_of_root (varp, &type_changed);
|
| + if (update_type_if_necessary(*varp, new))
|
| + type_changed = 1;
|
| r.varobj = *varp;
|
| -
|
| r.type_changed = type_changed;
|
| if (install_new_value ((*varp), new, type_changed))
|
| r.changed = 1;
|
| @@ -1850,9 +2044,30 @@ VEC(varobj_update_result) *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 (update_type_if_necessary(v, new))
|
| + r.type_changed = 1;
|
| + 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;
|
| + 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;
|
| @@ -1864,7 +2079,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| invoked. */
|
| if (v->pretty_printer)
|
| {
|
| - VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0;
|
| + VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0;
|
| + VEC (varobj_p) *new = 0;
|
| int i, children_changed = 0;
|
|
|
| if (v->frozen)
|
| @@ -1882,7 +2098,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| it. */
|
| if (!varobj_has_more (v, 0))
|
| {
|
| - update_dynamic_varobj_children (v, NULL, NULL, NULL,
|
| + update_dynamic_varobj_children (v, NULL, NULL, NULL, NULL,
|
| &dummy, 0, 0, 0);
|
| if (varobj_has_more (v, 0))
|
| r.changed = 1;
|
| @@ -1896,8 +2112,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
|
|
| /* If update_dynamic_varobj_children returns 0, then we have
|
| a non-conforming pretty-printer, so we skip it. */
|
| - if (update_dynamic_varobj_children (v, &changed, &new, &unchanged,
|
| - &children_changed, 1,
|
| + if (update_dynamic_varobj_children (v, &changed, &type_changed, &new,
|
| + &unchanged, &children_changed, 1,
|
| v->from, v->to))
|
| {
|
| if (children_changed || new)
|
| @@ -1909,6 +2125,18 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| popped from the work stack first, and so will be
|
| added to result first. This does not affect
|
| correctness, just "nicer". */
|
| + for (i = VEC_length (varobj_p, type_changed) - 1; i >= 0; --i)
|
| + {
|
| + varobj_p tmp = VEC_index (varobj_p, type_changed, i);
|
| + varobj_update_result r = {0};
|
| +
|
| + /* Type may change only if value was changed. */
|
| + r.varobj = tmp;
|
| + r.changed = 1;
|
| + r.type_changed = 1;
|
| + r.value_installed = 1;
|
| + VEC_safe_push (varobj_update_result, stack, &r);
|
| + }
|
| for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i)
|
| {
|
| varobj_p tmp = VEC_index (varobj_p, changed, i);
|
| @@ -1935,9 +2163,10 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
|
| if (r.changed || r.children_changed)
|
| VEC_safe_push (varobj_update_result, result, &r);
|
|
|
| - /* Free CHANGED and UNCHANGED, but not NEW, because NEW
|
| - has been put into the result vector. */
|
| + /* Free CHANGED, TYPE_CHANGED and UNCHANGED, but not NEW,
|
| + because NEW has been put into the result vector. */
|
| VEC_free (varobj_p, changed);
|
| + VEC_free (varobj_p, type_changed);
|
| VEC_free (varobj_p, unchanged);
|
|
|
| continue;
|
| @@ -2169,6 +2398,20 @@ create_child (struct varobj *parent, int index, char *name)
|
| value_of_child (parent, index));
|
| }
|
|
|
| +/* Does CHILD represent a child with no name? This happens when
|
| + the child is an anonmous struct or union and it has no field name
|
| + in its parent variable.
|
| +
|
| + This has already been determined by *_describe_child. The easiest
|
| + thing to do is to compare the child's name with ANONYMOUS_*_NAME. */
|
| +
|
| +static int
|
| +is_anonymous_child (struct varobj *child)
|
| +{
|
| + return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
|
| + || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
|
| +}
|
| +
|
| static struct varobj *
|
| create_child_with_value (struct varobj *parent, int index, const char *name,
|
| struct value *value)
|
| @@ -2184,8 +2427,13 @@ create_child_with_value (struct varobj *parent, int index, const char *name,
|
| child->index = index;
|
| child->parent = parent;
|
| child->root = parent->root;
|
| - childs_name = xstrprintf ("%s.%s", parent->obj_name, name);
|
| +
|
| + if (is_anonymous_child (child))
|
| + childs_name = xstrprintf ("%s.%d_anonymous", parent->obj_name, index);
|
| + else
|
| + childs_name = xstrprintf ("%s.%s", parent->obj_name, name);
|
| child->obj_name = childs_name;
|
| +
|
| install_variable (child);
|
|
|
| /* Compute the type of the child. Must do this before
|
| @@ -2193,7 +2441,7 @@ create_child_with_value (struct varobj *parent, int index, const char *name,
|
| if (value != NULL)
|
| /* If the child had no evaluation errors, var->value
|
| will be non-NULL and contain a valid type. */
|
| - child->type = value_type (value);
|
| + child->type = value_actual_type (value, 0, NULL);
|
| else
|
| /* Otherwise, we must compute the type. */
|
| child->type = (*child->root->lang->type_of_child) (child->parent,
|
| @@ -2540,7 +2788,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;
|
| + var->from = -1;
|
| + *type_changed = 1;
|
| + }
|
| + return value;
|
| + }
|
| }
|
|
|
| /* What is the ``struct value *'' for the INDEX'th child of PARENT? */
|
| @@ -2729,39 +2998,12 @@ varobj_editable_p (struct varobj *var)
|
| }
|
| }
|
|
|
| -/* 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
|
| - changes of such values. This makes sense for structures
|
| - (since the changes in children values will be reported separately),
|
| - or for artifical objects (like 'public' pseudo-field in C++).
|
| +/* Call VAR's value_is_changeable_p language-specific callback. */
|
|
|
| - Return value of 0 means that gdb need not call value_fetch_lazy
|
| - for the value of this variable object. */
|
| static int
|
| varobj_value_is_changeable_p (struct varobj *var)
|
| {
|
| - int r;
|
| - struct type *type;
|
| -
|
| - if (CPLUS_FAKE_CHILD (var))
|
| - return 0;
|
| -
|
| - type = get_value_type (var);
|
| -
|
| - switch (TYPE_CODE (type))
|
| - {
|
| - case TYPE_CODE_STRUCT:
|
| - case TYPE_CODE_UNION:
|
| - case TYPE_CODE_ARRAY:
|
| - r = 0;
|
| - break;
|
| -
|
| - default:
|
| - r = 1;
|
| - }
|
| -
|
| - return r;
|
| + return var->root->lang->value_is_changeable_p (var);
|
| }
|
|
|
| /* Return 1 if that varobj is floating, that is is always evaluated in the
|
| @@ -2780,6 +3022,10 @@ varobj_floating_p (struct varobj *var)
|
| to all types and dereferencing pointers to
|
| structures.
|
|
|
| + If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
|
| + value will be fetched and if it differs from static type
|
| + the value will be casted to it.
|
| +
|
| 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
|
| @@ -2791,7 +3037,8 @@ varobj_floating_p (struct varobj *var)
|
| static void
|
| adjust_value_for_child_access (struct value **value,
|
| struct type **type,
|
| - int *was_ptr)
|
| + int *was_ptr,
|
| + int lookup_actual_type)
|
| {
|
| gdb_assert (type && *type);
|
|
|
| @@ -2817,9 +3064,14 @@ adjust_value_for_child_access (struct value **value,
|
| {
|
| if (value && *value)
|
| {
|
| - int success = gdb_value_ind (*value, value);
|
| + volatile struct gdb_exception except;
|
|
|
| - if (!success)
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + *value = value_ind (*value);
|
| + }
|
| +
|
| + if (except.reason < 0)
|
| *value = NULL;
|
| }
|
| *type = target_type;
|
| @@ -2831,9 +3083,53 @@ adjust_value_for_child_access (struct value **value,
|
| /* The 'get_target_type' function calls check_typedef on
|
| result, so we can immediately check type code. No
|
| need to call check_typedef here. */
|
| +
|
| + /* Access a real type of the value (if necessary and possible). */
|
| + if (value && *value && lookup_actual_type)
|
| + {
|
| + struct type *enclosing_type;
|
| + int real_type_found = 0;
|
| +
|
| + enclosing_type = value_actual_type (*value, 1, &real_type_found);
|
| + if (real_type_found)
|
| + {
|
| + *type = enclosing_type;
|
| + *value = value_cast (enclosing_type, *value);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/* Implement the "value_is_changeable_p" varobj callback for most
|
| + languages. */
|
| +
|
| +static int
|
| +default_value_is_changeable_p (struct varobj *var)
|
| +{
|
| + int r;
|
| + struct type *type;
|
| +
|
| + if (CPLUS_FAKE_CHILD (var))
|
| + return 0;
|
| +
|
| + type = get_value_type (var);
|
| +
|
| + switch (TYPE_CODE (type))
|
| + {
|
| + case TYPE_CODE_STRUCT:
|
| + case TYPE_CODE_UNION:
|
| + case TYPE_CODE_ARRAY:
|
| + r = 0;
|
| + break;
|
| +
|
| + default:
|
| + r = 1;
|
| + }
|
| +
|
| + return r;
|
| }
|
|
|
| /* C */
|
| +
|
| static int
|
| c_number_of_children (struct varobj *var)
|
| {
|
| @@ -2841,7 +3137,7 @@ c_number_of_children (struct varobj *var)
|
| int children = 0;
|
| struct type *target;
|
|
|
| - adjust_value_for_child_access (NULL, &type, NULL);
|
| + adjust_value_for_child_access (NULL, &type, NULL, 0);
|
| target = get_target_type (type);
|
|
|
| switch (TYPE_CODE (type))
|
| @@ -2944,6 +3240,7 @@ c_describe_child (struct varobj *parent, int index,
|
| struct type *type = get_value_type (parent);
|
| char *parent_expression = NULL;
|
| int was_ptr;
|
| + volatile struct gdb_exception except;
|
|
|
| if (cname)
|
| *cname = NULL;
|
| @@ -2954,9 +3251,9 @@ c_describe_child (struct varobj *parent, int index,
|
| if (cfull_expression)
|
| {
|
| *cfull_expression = NULL;
|
| - parent_expression = varobj_get_path_expr (parent);
|
| + parent_expression = varobj_get_path_expr (get_path_expr_parent (parent));
|
| }
|
| - adjust_value_for_child_access (&value, &type, &was_ptr);
|
| + adjust_value_for_child_access (&value, &type, &was_ptr, 0);
|
|
|
| switch (TYPE_CODE (type))
|
| {
|
| @@ -2971,7 +3268,10 @@ c_describe_child (struct varobj *parent, int index,
|
| {
|
| int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
|
|
|
| - gdb_value_subscript (value, real_index, cvalue);
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + *cvalue = value_subscript (value, real_index);
|
| + }
|
| }
|
|
|
| if (ctype)
|
| @@ -2989,26 +3289,49 @@ c_describe_child (struct varobj *parent, int index,
|
|
|
| case TYPE_CODE_STRUCT:
|
| case TYPE_CODE_UNION:
|
| - if (cname)
|
| - *cname = xstrdup (TYPE_FIELD_NAME (type, index));
|
| + {
|
| + const char *field_name;
|
|
|
| - if (cvalue && value)
|
| - {
|
| - /* For C, varobj index is the same as type index. */
|
| - *cvalue = value_struct_element_index (value, index);
|
| - }
|
| + /* If the type is anonymous and the field has no name,
|
| + set an appropriate name. */
|
| + field_name = TYPE_FIELD_NAME (type, index);
|
| + if (field_name == NULL || *field_name == '\0')
|
| + {
|
| + if (cname)
|
| + {
|
| + if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
|
| + == TYPE_CODE_STRUCT)
|
| + *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
|
| + else
|
| + *cname = xstrdup (ANONYMOUS_UNION_NAME);
|
| + }
|
|
|
| - if (ctype)
|
| - *ctype = TYPE_FIELD_TYPE (type, index);
|
| + if (cfull_expression)
|
| + *cfull_expression = xstrdup ("");
|
| + }
|
| + else
|
| + {
|
| + if (cname)
|
| + *cname = xstrdup (field_name);
|
|
|
| - if (cfull_expression)
|
| - {
|
| - char *join = was_ptr ? "->" : ".";
|
| + if (cfull_expression)
|
| + {
|
| + char *join = was_ptr ? "->" : ".";
|
|
|
| - *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join,
|
| - TYPE_FIELD_NAME (type, index));
|
| - }
|
| + *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
|
| + join, field_name);
|
| + }
|
| + }
|
| +
|
| + if (cvalue && value)
|
| + {
|
| + /* For C, varobj index is the same as type index. */
|
| + *cvalue = value_struct_element_index (value, index);
|
| + }
|
|
|
| + if (ctype)
|
| + *ctype = TYPE_FIELD_TYPE (type, index);
|
| + }
|
| break;
|
|
|
| case TYPE_CODE_PTR:
|
| @@ -3017,9 +3340,12 @@ c_describe_child (struct varobj *parent, int index,
|
|
|
| if (cvalue && value)
|
| {
|
| - int success = gdb_value_ind (value, cvalue);
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + *cvalue = value_ind (value);
|
| + }
|
|
|
| - if (!success)
|
| + if (except.reason < 0)
|
| *cvalue = NULL;
|
| }
|
|
|
| @@ -3123,9 +3449,15 @@ c_value_of_root (struct varobj **var_handle)
|
|
|
| if (within_scope)
|
| {
|
| + volatile struct gdb_exception except;
|
| +
|
| /* We need to catch errors here, because if evaluate
|
| expression fails we want to just return NULL. */
|
| - gdb_evaluate_expression (var->root->exp, &new_val);
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + new_val = evaluate_expression (var->root->exp);
|
| + }
|
| +
|
| return new_val;
|
| }
|
|
|
| @@ -3160,11 +3492,6 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
| catch that case explicitly. */
|
| struct type *type = get_type (var);
|
|
|
| - /* If we have a custom formatter, return whatever string it has
|
| - produced. */
|
| - if (var->pretty_printer && var->print_value)
|
| - return xstrdup (var->print_value);
|
| -
|
| /* Strip top-level references. */
|
| while (TYPE_CODE (type) == TYPE_CODE_REF)
|
| type = check_typedef (TYPE_TARGET_TYPE (type));
|
| @@ -3222,16 +3549,29 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
| static int
|
| cplus_number_of_children (struct varobj *var)
|
| {
|
| + struct value *value = NULL;
|
| struct type *type;
|
| int children, dont_know;
|
| + int lookup_actual_type = 0;
|
| + struct value_print_options opts;
|
|
|
| dont_know = 1;
|
| children = 0;
|
|
|
| + get_user_print_options (&opts);
|
| +
|
| if (!CPLUS_FAKE_CHILD (var))
|
| {
|
| type = get_value_type (var);
|
| - adjust_value_for_child_access (NULL, &type, NULL);
|
| +
|
| + /* It is necessary to access a real type (via RTTI). */
|
| + if (opts.objectprint)
|
| + {
|
| + value = var->value;
|
| + lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
|
| + || TYPE_CODE (var->type) == TYPE_CODE_PTR);
|
| + }
|
| + adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
|
|
|
| if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
|
| ((TYPE_CODE (type)) == TYPE_CODE_UNION))
|
| @@ -3258,7 +3598,17 @@ cplus_number_of_children (struct varobj *var)
|
| int kids[3];
|
|
|
| type = get_value_type (var->parent);
|
| - adjust_value_for_child_access (NULL, &type, NULL);
|
| +
|
| + /* It is necessary to access a real type (via RTTI). */
|
| + if (opts.objectprint)
|
| + {
|
| + struct varobj *parent = var->parent;
|
| +
|
| + value = parent->value;
|
| + lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
|
| + || TYPE_CODE (parent->type) == TYPE_CODE_PTR);
|
| + }
|
| + adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
|
|
|
| cplus_class_num_children (type, kids);
|
| if (strcmp (var->name, "public") == 0)
|
| @@ -3340,7 +3690,10 @@ cplus_describe_child (struct varobj *parent, int index,
|
| struct value *value;
|
| struct type *type;
|
| int was_ptr;
|
| + int lookup_actual_type = 0;
|
| char *parent_expression = NULL;
|
| + struct varobj *var;
|
| + struct value_print_options opts;
|
|
|
| if (cname)
|
| *cname = NULL;
|
| @@ -3351,22 +3704,18 @@ cplus_describe_child (struct varobj *parent, int index,
|
| 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);
|
| - }
|
| + get_user_print_options (&opts);
|
|
|
| - adjust_value_for_child_access (&value, &type, &was_ptr);
|
| + var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
|
| + if (opts.objectprint)
|
| + lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
|
| + || TYPE_CODE (var->type) == TYPE_CODE_PTR);
|
| + value = var->value;
|
| + type = get_value_type (var);
|
| + if (cfull_expression)
|
| + parent_expression = varobj_get_path_expr (get_path_expr_parent (var));
|
| +
|
| + adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
|
|
|
| if (TYPE_CODE (type) == TYPE_CODE_STRUCT
|
| || TYPE_CODE (type) == TYPE_CODE_UNION)
|
| @@ -3385,6 +3734,7 @@ cplus_describe_child (struct varobj *parent, int index,
|
| enum accessibility acc = public_field;
|
| int vptr_fieldno;
|
| struct type *basetype = NULL;
|
| + const char *field_name;
|
|
|
| vptr_fieldno = get_vptr_fieldno (type, &basetype);
|
| if (strcmp (parent->name, "private") == 0)
|
| @@ -3403,20 +3753,40 @@ cplus_describe_child (struct varobj *parent, int index,
|
| }
|
| --type_index;
|
|
|
| - if (cname)
|
| - *cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
|
| + /* If the type is anonymous and the field has no name,
|
| + set an appopriate name. */
|
| + field_name = TYPE_FIELD_NAME (type, type_index);
|
| + if (field_name == NULL || *field_name == '\0')
|
| + {
|
| + if (cname)
|
| + {
|
| + if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
|
| + == TYPE_CODE_STRUCT)
|
| + *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
|
| + else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
|
| + == TYPE_CODE_UNION)
|
| + *cname = xstrdup (ANONYMOUS_UNION_NAME);
|
| + }
|
| +
|
| + if (cfull_expression)
|
| + *cfull_expression = xstrdup ("");
|
| + }
|
| + else
|
| + {
|
| + if (cname)
|
| + *cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
|
| +
|
| + if (cfull_expression)
|
| + *cfull_expression
|
| + = xstrprintf ("((%s)%s%s)", parent_expression, join,
|
| + field_name);
|
| + }
|
|
|
| if (cvalue && value)
|
| *cvalue = value_struct_element_index (value, type_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))
|
| {
|
| @@ -3648,7 +4018,7 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
| static int
|
| ada_number_of_children (struct varobj *var)
|
| {
|
| - return c_number_of_children (var);
|
| + return ada_varobj_get_number_of_children (var->value, var->type);
|
| }
|
|
|
| static char *
|
| @@ -3660,13 +4030,21 @@ ada_name_of_variable (struct varobj *parent)
|
| static char *
|
| ada_name_of_child (struct varobj *parent, int index)
|
| {
|
| - return c_name_of_child (parent, index);
|
| + return ada_varobj_get_name_of_child (parent->value, parent->type,
|
| + parent->name, index);
|
| }
|
|
|
| static char*
|
| ada_path_expr_of_child (struct varobj *child)
|
| {
|
| - return c_path_expr_of_child (child);
|
| + struct varobj *parent = child->parent;
|
| + const char *parent_path_expr = varobj_get_path_expr (parent);
|
| +
|
| + return ada_varobj_get_path_expr_of_child (parent->value,
|
| + parent->type,
|
| + parent->name,
|
| + parent_path_expr,
|
| + child->index);
|
| }
|
|
|
| static struct value *
|
| @@ -3678,19 +4056,92 @@ ada_value_of_root (struct varobj **var_handle)
|
| static struct value *
|
| ada_value_of_child (struct varobj *parent, int index)
|
| {
|
| - return c_value_of_child (parent, index);
|
| + return ada_varobj_get_value_of_child (parent->value, parent->type,
|
| + parent->name, index);
|
| }
|
|
|
| static struct type *
|
| ada_type_of_child (struct varobj *parent, int index)
|
| {
|
| - return c_type_of_child (parent, index);
|
| + return ada_varobj_get_type_of_child (parent->value, parent->type,
|
| + index);
|
| }
|
|
|
| static char *
|
| ada_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
| {
|
| - return c_value_of_variable (var, format);
|
| + struct value_print_options opts;
|
| +
|
| + get_formatted_print_options (&opts, format_code[(int) format]);
|
| + opts.deref_ref = 0;
|
| + opts.raw = 1;
|
| +
|
| + return ada_varobj_get_value_of_variable (var->value, var->type, &opts);
|
| +}
|
| +
|
| +/* Implement the "value_is_changeable_p" routine for Ada. */
|
| +
|
| +static int
|
| +ada_value_is_changeable_p (struct varobj *var)
|
| +{
|
| + struct type *type = var->value ? value_type (var->value) : var->type;
|
| +
|
| + if (ada_is_array_descriptor_type (type)
|
| + && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
|
| + {
|
| + /* This is in reality a pointer to an unconstrained array.
|
| + its value is changeable. */
|
| + return 1;
|
| + }
|
| +
|
| + if (ada_is_string_type (type))
|
| + {
|
| + /* We display the contents of the string in the array's
|
| + "value" field. The contents can change, so consider
|
| + that the array is changeable. */
|
| + return 1;
|
| + }
|
| +
|
| + return default_value_is_changeable_p (var);
|
| +}
|
| +
|
| +/* 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)
|
| +{
|
| + int i;
|
| + int from = -1;
|
| + int to = -1;
|
| +
|
| + /* If the number of fields have changed, then for sure the type
|
| + has mutated. */
|
| + if (ada_varobj_get_number_of_children (new_val, new_type)
|
| + != var->num_children)
|
| + return 1;
|
| +
|
| + /* If the number of fields have remained the same, then we need
|
| + to check the name of each field. If they remain the same,
|
| + then chances are the type hasn't mutated. This is technically
|
| + an incomplete test, as the child's type might have changed
|
| + despite the fact that the name remains the same. But we'll
|
| + handle this situation by saying that the child has mutated,
|
| + not this value.
|
| +
|
| + If only part (or none!) of the children have been fetched,
|
| + then only check the ones we fetched. It does not matter
|
| + to the frontend whether a child that it has not fetched yet
|
| + has mutated or not. So just assume it hasn't. */
|
| +
|
| + restrict_range (var->children, &from, &to);
|
| + for (i = from; i < to; i++)
|
| + if (strcmp (ada_varobj_get_name_of_child (new_val, new_type,
|
| + var->name, i),
|
| + VEC_index (varobj_p, var->children, i)->name) != 0)
|
| + return 1;
|
| +
|
| + return 0;
|
| }
|
|
|
| /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
|
|
|