Replace VEC (varobj_update_result) with std::vector

This patch replaces makes varobj_update return an std::vector, and
updates the fallouts.

To make that easier, the varobj_update_result is c++ified a bit.  I
added a constructor and initialized its fields in-class.  The newobj
vector is also made an std::vector, so that it's automatically freed
when varobj_update_result is destroyed and handled correctly by the
default move constructor.  I disabled copy constructor and assignment
for that structure, because normally it never needs to be copied, only
moved.

As a result, the newobj parameter of update_dynamic_varobj_children must
be changed to an std::vector.  The patch converts the other vector
parameters of update_dynamic_varobj_children to std::vector.  It's not
strictly necessary to do it in the same patch, but I think it makes
sense to do it.

gdb/ChangeLog:

	* varobj.h (struct varobj_update_result): Add constructor, add
	move constructor, disable copy and assign, initialize fields.
	<newobj>: Change type to std::vector.
	(varobj_update): Return std::vector.
	* varobj.c (install_dynamic_child): Change VEC parameters to
	std::vector and adjust.
	(update_dynamic_varobj_children): Likewise.
	(varobj_update): Return std::vector and adjust.
	* mi/mi-cmd-var.c (varobj_update_one): Adjust to vector changes.
This commit is contained in:
Simon Marchi 2017-11-22 15:08:06 -05:00 committed by Simon Marchi
parent ddf0ea085b
commit 0604393c22
4 changed files with 107 additions and 129 deletions

View File

@ -1,3 +1,15 @@
2017-11-22 Simon Marchi <simon.marchi@polymtl.ca>
* varobj.h (struct varobj_update_result): Add constructor, add
move constructor, disable copy and assign, initialize fields.
<newobj>: Change type to std::vector.
(varobj_update): Return std::vector.
* varobj.c (install_dynamic_child): Change VEC parameters to
std::vector and adjust.
(update_dynamic_varobj_children): Likewise.
(varobj_update): Return std::vector and adjust.
* mi/mi-cmd-var.c (varobj_update_one): Adjust to vector changes.
2017-11-22 Simon Marchi <simon.marchi@polymtl.ca> 2017-11-22 Simon Marchi <simon.marchi@polymtl.ca>
* varobj.h (struct varobj) <parent>: Remove const. * varobj.h (struct varobj) <parent>: Remove const.

View File

@ -685,27 +685,24 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
int is_explicit) int is_explicit)
{ {
struct ui_out *uiout = current_uiout; struct ui_out *uiout = current_uiout;
VEC (varobj_update_result) *changes;
varobj_update_result *r; std::vector<varobj_update_result> changes = varobj_update (&var, is_explicit);
int i;
changes = varobj_update (&var, is_explicit); for (const varobj_update_result &r : changes)
for (i = 0; VEC_iterate (varobj_update_result, changes, i, r); ++i)
{ {
int from, to; int from, to;
gdb::optional<ui_out_emit_tuple> tuple_emitter; gdb::optional<ui_out_emit_tuple> tuple_emitter;
if (mi_version (uiout) > 1) if (mi_version (uiout) > 1)
tuple_emitter.emplace (uiout, nullptr); tuple_emitter.emplace (uiout, nullptr);
uiout->field_string ("name", varobj_get_objname (r->varobj)); uiout->field_string ("name", varobj_get_objname (r.varobj));
switch (r->status) switch (r.status)
{ {
case VAROBJ_IN_SCOPE: case VAROBJ_IN_SCOPE:
if (mi_print_value_p (r->varobj, print_values)) if (mi_print_value_p (r.varobj, print_values))
{ {
std::string val = varobj_get_value (r->varobj); std::string val = varobj_get_value (r.varobj);
uiout->field_string ("value", val.c_str ()); uiout->field_string ("value", val.c_str ());
} }
@ -719,53 +716,47 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
break; break;
} }
if (r->status != VAROBJ_INVALID) if (r.status != VAROBJ_INVALID)
{ {
if (r->type_changed) if (r.type_changed)
uiout->field_string ("type_changed", "true"); uiout->field_string ("type_changed", "true");
else else
uiout->field_string ("type_changed", "false"); uiout->field_string ("type_changed", "false");
} }
if (r->type_changed) if (r.type_changed)
{ {
std::string type_name = varobj_get_type (r->varobj); std::string type_name = varobj_get_type (r.varobj);
uiout->field_string ("new_type", type_name.c_str ()); uiout->field_string ("new_type", type_name.c_str ());
} }
if (r->type_changed || r->children_changed) if (r.type_changed || r.children_changed)
uiout->field_int ("new_num_children", uiout->field_int ("new_num_children",
varobj_get_num_children (r->varobj)); varobj_get_num_children (r.varobj));
gdb::unique_xmalloc_ptr<char> display_hint gdb::unique_xmalloc_ptr<char> display_hint
= varobj_get_display_hint (r->varobj); = varobj_get_display_hint (r.varobj);
if (display_hint) if (display_hint)
uiout->field_string ("displayhint", display_hint.get ()); uiout->field_string ("displayhint", display_hint.get ());
if (varobj_is_dynamic_p (r->varobj)) if (varobj_is_dynamic_p (r.varobj))
uiout->field_int ("dynamic", 1); uiout->field_int ("dynamic", 1);
varobj_get_child_range (r->varobj, &from, &to); varobj_get_child_range (r.varobj, &from, &to);
uiout->field_int ("has_more", varobj_has_more (r->varobj, to)); uiout->field_int ("has_more", varobj_has_more (r.varobj, to));
if (r->newobj) if (!r.newobj.empty ())
{ {
int j;
varobj_p child;
ui_out_emit_list list_emitter (uiout, "new_children"); ui_out_emit_list list_emitter (uiout, "new_children");
for (j = 0; VEC_iterate (varobj_p, r->newobj, j, child); ++j)
for (varobj *child : r.newobj)
{ {
ui_out_emit_tuple tuple_emitter (uiout, NULL); ui_out_emit_tuple tuple_emitter (uiout, NULL);
print_varobj (child, print_values, 1 /* print_expression */); print_varobj (child, print_values, 1 /* print_expression */);
} }
VEC_free (varobj_p, r->newobj);
r->newobj = NULL; /* Paranoia. */
} }
} }
VEC_free (varobj_update_result, changes);
} }
void void

View File

@ -629,10 +629,10 @@ varobj_restrict_range (const std::vector<varobj *> &children,
static void static void
install_dynamic_child (struct varobj *var, install_dynamic_child (struct varobj *var,
VEC (varobj_p) **changed, std::vector<varobj *> *changed,
VEC (varobj_p) **type_changed, std::vector<varobj *> *type_changed,
VEC (varobj_p) **newobj, std::vector<varobj *> *newobj,
VEC (varobj_p) **unchanged, std::vector<varobj *> *unchanged,
int *cchanged, int *cchanged,
int index, int index,
struct varobj_item *item) struct varobj_item *item)
@ -642,9 +642,9 @@ install_dynamic_child (struct varobj *var,
/* There's no child yet. */ /* There's no child yet. */
struct varobj *child = varobj_add_child (var, item); struct varobj *child = varobj_add_child (var, item);
if (newobj) if (newobj != NULL)
{ {
VEC_safe_push (varobj_p, *newobj, child); newobj->push_back (child);
*cchanged = 1; *cchanged = 1;
} }
} }
@ -655,16 +655,16 @@ install_dynamic_child (struct varobj *var,
if (type_updated) if (type_updated)
{ {
if (type_changed) if (type_changed != NULL)
VEC_safe_push (varobj_p, *type_changed, existing); type_changed->push_back (existing);
} }
if (install_new_value (existing, item->value, 0)) if (install_new_value (existing, item->value, 0))
{ {
if (!type_updated && changed) if (!type_updated && changed != NULL)
VEC_safe_push (varobj_p, *changed, existing); changed->push_back (existing);
} }
else if (!type_updated && unchanged) else if (!type_updated && unchanged != NULL)
VEC_safe_push (varobj_p, *unchanged, existing); unchanged->push_back (existing);
} }
} }
@ -713,10 +713,10 @@ varobj_clear_saved_item (struct varobj_dynamic *var)
static int static int
update_dynamic_varobj_children (struct varobj *var, update_dynamic_varobj_children (struct varobj *var,
VEC (varobj_p) **changed, std::vector<varobj *> *changed,
VEC (varobj_p) **type_changed, std::vector<varobj *> *type_changed,
VEC (varobj_p) **newobj, std::vector<varobj *> *newobj,
VEC (varobj_p) **unchanged, std::vector<varobj *> *unchanged,
int *cchanged, int *cchanged,
int update_children, int update_children,
int from, int from,
@ -1525,14 +1525,13 @@ varobj_value_has_mutated (const struct varobj *var, struct value *new_value,
returns TYPE_CHANGED, then it has done this and VARP will be modified returns TYPE_CHANGED, then it has done this and VARP will be modified
to point to the new varobj. */ to point to the new varobj. */
VEC(varobj_update_result) * std::vector<varobj_update_result>
varobj_update (struct varobj **varp, int is_explicit) varobj_update (struct varobj **varp, int is_explicit)
{ {
int type_changed = 0; int type_changed = 0;
int i;
struct value *newobj; struct value *newobj;
VEC (varobj_update_result) *stack = NULL; std::vector<varobj_update_result> stack;
VEC (varobj_update_result) *result = NULL; std::vector<varobj_update_result> result;
/* Frozen means frozen -- we don't check for any change in /* Frozen means frozen -- we don't check for any change in
this varobj, including its going out of scope, or this varobj, including its going out of scope, or
@ -1544,20 +1543,13 @@ varobj_update (struct varobj **varp, int is_explicit)
if (!(*varp)->root->is_valid) if (!(*varp)->root->is_valid)
{ {
varobj_update_result r = {0}; result.emplace_back (*varp, VAROBJ_INVALID);
r.varobj = *varp;
r.status = VAROBJ_INVALID;
VEC_safe_push (varobj_update_result, result, &r);
return result; return result;
} }
if ((*varp)->root->rootvar == *varp) if ((*varp)->root->rootvar == *varp)
{ {
varobj_update_result r = {0}; varobj_update_result r (*varp);
r.varobj = *varp;
r.status = VAROBJ_IN_SCOPE;
/* Update the root variable. value_of_root can return NULL /* Update the root variable. value_of_root can return NULL
if the variable is no longer around, i.e. we stepped out of if the variable is no longer around, i.e. we stepped out of
@ -1579,28 +1571,23 @@ varobj_update (struct varobj **varp, int is_explicit)
if (r.status == VAROBJ_NOT_IN_SCOPE) if (r.status == VAROBJ_NOT_IN_SCOPE)
{ {
if (r.type_changed || r.changed) if (r.type_changed || r.changed)
VEC_safe_push (varobj_update_result, result, &r); result.push_back (std::move (r));
return result; return result;
} }
VEC_safe_push (varobj_update_result, stack, &r); stack.push_back (std::move (r));
} }
else else
{ stack.emplace_back (*varp);
varobj_update_result r = {0};
r.varobj = *varp;
VEC_safe_push (varobj_update_result, stack, &r);
}
/* Walk through the children, reconstructing them all. */ /* Walk through the children, reconstructing them all. */
while (!VEC_empty (varobj_update_result, stack)) while (!stack.empty ())
{ {
varobj_update_result r = *(VEC_last (varobj_update_result, stack)); varobj_update_result r = std::move (stack.back ());
stack.pop_back ();
struct varobj *v = r.varobj; struct varobj *v = r.varobj;
VEC_pop (varobj_update_result, stack);
/* Update this variable, unless it's a root, which is already /* Update this variable, unless it's a root, which is already
updated. */ updated. */
if (!r.value_installed) if (!r.value_installed)
@ -1638,9 +1625,8 @@ varobj_update (struct varobj **varp, int is_explicit)
for which -var-list-children was never invoked. */ for which -var-list-children was never invoked. */
if (varobj_is_dynamic_p (v)) if (varobj_is_dynamic_p (v))
{ {
VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0; std::vector<varobj *> changed, type_changed, unchanged, newobj;
VEC (varobj_p) *newobj = 0; int children_changed = 0;
int i, children_changed = 0;
if (v->frozen) if (v->frozen)
continue; continue;
@ -1664,7 +1650,7 @@ varobj_update (struct varobj **varp, int is_explicit)
} }
if (r.changed) if (r.changed)
VEC_safe_push (varobj_update_result, result, &r); result.push_back (std::move (r));
continue; continue;
} }
@ -1675,58 +1661,48 @@ varobj_update (struct varobj **varp, int is_explicit)
&unchanged, &children_changed, 1, &unchanged, &children_changed, 1,
v->from, v->to)) v->from, v->to))
{ {
if (children_changed || newobj) if (children_changed || !newobj.empty ())
{ {
r.children_changed = 1; r.children_changed = 1;
r.newobj = newobj; r.newobj = std::move (newobj);
} }
/* Push in reverse order so that the first child is /* Push in reverse order so that the first child is
popped from the work stack first, and so will be popped from the work stack first, and so will be
added to result first. This does not affect added to result first. This does not affect
correctness, just "nicer". */ correctness, just "nicer". */
for (i = VEC_length (varobj_p, type_changed) - 1; i >= 0; --i) for (int i = type_changed.size () - 1; i >= 0; --i)
{ {
varobj_p tmp = VEC_index (varobj_p, type_changed, i); varobj_update_result r (type_changed[i]);
varobj_update_result r = {0};
/* Type may change only if value was changed. */ /* Type may change only if value was changed. */
r.varobj = tmp;
r.changed = 1; r.changed = 1;
r.type_changed = 1; r.type_changed = 1;
r.value_installed = 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);
varobj_update_result r = {0};
r.varobj = tmp; stack.push_back (std::move (r));
}
for (int i = changed.size () - 1; i >= 0; --i)
{
varobj_update_result r (changed[i]);
r.changed = 1; r.changed = 1;
r.value_installed = 1; r.value_installed = 1;
VEC_safe_push (varobj_update_result, stack, &r);
stack.push_back (std::move (r));
} }
for (i = VEC_length (varobj_p, unchanged) - 1; i >= 0; --i) for (int i = unchanged.size () - 1; i >= 0; --i)
{ {
varobj_p tmp = VEC_index (varobj_p, unchanged, i); if (!unchanged[i]->frozen)
{
varobj_update_result r (unchanged[i]);
if (!tmp->frozen) r.value_installed = 1;
{
varobj_update_result r = {0};
r.varobj = tmp; stack.push_back (std::move (r));
r.value_installed = 1; }
VEC_safe_push (varobj_update_result, stack, &r); }
}
}
if (r.changed || r.children_changed) if (r.changed || r.children_changed)
VEC_safe_push (varobj_update_result, result, &r); result.push_back (std::move (r));
/* 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; continue;
} }
@ -1736,29 +1712,21 @@ varobj_update (struct varobj **varp, int is_explicit)
child is popped from the work stack first, and so child is popped from the work stack first, and so
will be added to result first. This does not will be added to result first. This does not
affect correctness, just "nicer". */ affect correctness, just "nicer". */
for (i = v->children.size () - 1; i >= 0; --i) for (int i = v->children.size () - 1; i >= 0; --i)
{ {
varobj *c = v->children[i]; varobj *c = v->children[i];
/* Child may be NULL if explicitly deleted by -var-delete. */ /* Child may be NULL if explicitly deleted by -var-delete. */
if (c != NULL && !c->frozen) if (c != NULL && !c->frozen)
{ stack.emplace_back (c);
varobj_update_result r = {0};
r.varobj = c;
VEC_safe_push (varobj_update_result, stack, &r);
}
} }
if (r.changed || r.type_changed) if (r.changed || r.type_changed)
VEC_safe_push (varobj_update_result, result, &r); result.push_back (std::move (r));
} }
VEC_free (varobj_update_result, stack);
return result; return result;
} }
/* Helper functions */ /* Helper functions */

View File

@ -60,26 +60,33 @@ struct varobj;
typedef struct varobj *varobj_p; typedef struct varobj *varobj_p;
DEF_VEC_P (varobj_p); DEF_VEC_P (varobj_p);
typedef struct varobj_update_result_t struct varobj_update_result
{ {
varobj_update_result (struct varobj *varobj_,
varobj_scope_status status_ = VAROBJ_IN_SCOPE)
: varobj (varobj_), status (status_)
{}
varobj_update_result (varobj_update_result &&other) = default;
DISABLE_COPY_AND_ASSIGN (varobj_update_result);
struct varobj *varobj; struct varobj *varobj;
int type_changed; int type_changed = 0;
int children_changed; int children_changed = 0;
int changed; int changed = 0;
enum varobj_scope_status status; enum varobj_scope_status status;
/* This variable is used internally by varobj_update to indicate if the /* This variable is used internally by varobj_update to indicate if the
new value of varobj is already computed and installed, or has to new value of varobj is already computed and installed, or has to
be yet installed. Don't use this outside varobj.c. */ be yet installed. Don't use this outside varobj.c. */
int value_installed; int value_installed = 0;
/* This will be non-NULL when new children were added to the varobj. /* This will be non-NULL when new children were added to the varobj.
It lists the new children (which must necessarily come at the end It lists the new children (which must necessarily come at the end
of the child list) added during an update. The caller is of the child list) added during an update. The caller is
responsible for freeing this vector. */ responsible for freeing this vector. */
VEC (varobj_p) *newobj; std::vector<struct varobj *> newobj;
} varobj_update_result; };
DEF_VEC_O (varobj_update_result);
struct varobj_root; struct varobj_root;
struct varobj_dynamic; struct varobj_dynamic;
@ -305,8 +312,8 @@ extern int varobj_set_value (struct varobj *var, const char *expression);
extern void all_root_varobjs (void (*func) (struct varobj *var, void *data), extern void all_root_varobjs (void (*func) (struct varobj *var, void *data),
void *data); void *data);
extern VEC(varobj_update_result) *varobj_update (struct varobj **varp, extern std::vector<varobj_update_result>
int is_explicit); varobj_update (struct varobj **varp, int is_explicit);
extern void varobj_invalidate (void); extern void varobj_invalidate (void);