/* 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
{
char *p;
enum varobj_languages lang;
- struct value *value;
+ struct value *value = NULL;
/* 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
if (fi != NULL)
{
var->root->frame = get_frame_id (fi);
- old_fi = deprecated_selected_frame;
+ old_fi = get_selected_frame (NULL);
select_frame (fi);
}
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 */
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)
{
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
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,
{
/* 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)
}
/* 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));
< 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 error = 0;
- int type_changed;
+ int type_changed = 0;
int i;
int vleft;
struct varobj *v;
struct frame_info *fi;
/* sanity check: have we been passed a pointer? */
- if (changelist == NULL)
- return WRONG_PARAM;
-
- /* Only root variables can be updated... */
- if (!is_root_p (*varp))
- /* Not a root var. */
- return WRONG_PARAM;
+ gdb_assert (changelist);
+
+ /* 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_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);
+
+ /* 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;
+ 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);
{
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 */))
}
*cv = 0;
+ VEC_free (varobj_p, stack);
+ VEC_free (varobj_p, result);
+
if (type_changed)
return TYPE_CHANGED;
else
var->root = NULL;
var->updated = 0;
var->print_value = NULL;
+ var->frozen = 0;
+ var->not_fetched = 0;
return 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);