/* Implementation of the GDB variable objects API.
- Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "gdbcmd.h"
#include "block.h"
#include "valprint.h"
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
#include "varobj.h"
#include "gdbthread.h"
show_varobjdebug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Varobj debugging is %s.\n"), value);
+ gdb_printf (file, _("Varobj debugging is %s.\n"), value);
}
/* String representations of gdb's format codes. */
/* The iterator returned by the printer's 'children' method, or NULL
if not available. */
- struct varobj_iter *child_iter = NULL;
+ std::unique_ptr<varobj_iter> child_iter;
/* We request one extra item from the iterator, so that we can
report to the caller whether there are more items than we have
static void delete_variable_1 (int *, struct varobj *, bool, bool);
-static bool install_variable (struct varobj *);
+static void install_variable (struct varobj *);
static void uninstall_variable (struct varobj *);
}
/* Don't allow variables to be created for types. */
- if (var->root->exp->elts[0].opcode == OP_TYPE
- || var->root->exp->elts[0].opcode == OP_TYPEOF
- || var->root->exp->elts[0].opcode == OP_DECLTYPE)
+ enum exp_opcode opcode = var->root->exp->first_opcode ();
+ if (opcode == OP_TYPE
+ || opcode == OP_TYPEOF
+ || opcode == OP_DECLTYPE)
{
- fprintf_unfiltered (gdb_stderr, "Attempt to use a type name"
- " as an expression.\n");
+ gdb_printf (gdb_stderr, "Attempt to use a type name"
+ " as an expression.\n");
return NULL;
}
if ((var != NULL) && (objname != NULL))
{
var->obj_name = objname;
-
- /* If a varobj name is duplicated, the install will fail so
- we must cleanup. */
- if (!install_variable (var.get ()))
- return NULL;
+ install_variable (var.get ());
}
return var.release ();
static PyObject *
instantiate_pretty_printer (PyObject *constructor, struct value *value)
{
- PyObject *val_obj = NULL;
- PyObject *printer;
-
- val_obj = value_to_value_object (value);
- if (! val_obj)
+ gdbpy_ref<> val_obj (value_to_value_object (value));
+ if (val_obj == nullptr)
return NULL;
- printer = PyObject_CallFunctionObjArgs (constructor, val_obj, NULL);
- Py_DECREF (val_obj);
- return printer;
+ return PyObject_CallFunctionObjArgs (constructor, val_obj.get (), NULL);
}
#endif
else
{
varobj *existing = var->children[index];
- bool type_updated = update_type_if_necessary (existing, item->value);
+ bool type_updated = update_type_if_necessary (existing,
+ item->value.get ());
if (type_updated)
{
if (type_changed != NULL)
type_changed->push_back (existing);
}
- if (install_new_value (existing, item->value, 0))
+ if (install_new_value (existing, item->value.get (), 0))
{
if (!type_updated && changed != NULL)
changed->push_back (existing);
/* A factory for creating dynamic varobj's iterators. Returns an
iterator object suitable for iterating over VAR's children. */
-static struct varobj_iter *
+static std::unique_ptr<varobj_iter>
varobj_get_iterator (struct varobj *var)
{
#if HAVE_PYTHON
return py_varobj_get_iterator (var, var->dynamic->pretty_printer);
#endif
- gdb_assert_not_reached (_("\
-requested an iterator from a non-dynamic varobj"));
-}
-
-/* Release and clear VAR's saved item, if any. */
-
-static void
-varobj_clear_saved_item (struct varobj_dynamic *var)
-{
- if (var->saved_item != NULL)
- {
- value_decref (var->saved_item->value);
- var->saved_item.reset (nullptr);
- }
+ gdb_assert_not_reached ("requested an iterator from a non-dynamic varobj");
}
static bool
if (update_children || var->dynamic->child_iter == NULL)
{
- delete var->dynamic->child_iter;
var->dynamic->child_iter = varobj_get_iterator (var);
-
- varobj_clear_saved_item (var->dynamic);
+ var->dynamic->saved_item.reset (nullptr);
i = 0;
if (var->dynamic->saved_item != NULL)
item = std::move (var->dynamic->saved_item);
else
- {
- item = var->dynamic->child_iter->next ();
- /* Release vitem->value so its lifetime is not bound to the
- execution of a command. */
- if (item != NULL && item->value != NULL)
- item->value = release_value (item->value).release ();
- }
+ item = var->dynamic->child_iter->next ();
if (item == NULL)
{
/* Iteration is done. Remove iterator from VAR. */
- delete var->dynamic->child_iter;
- var->dynamic->child_iter = NULL;
+ var->dynamic->child_iter.reset (nullptr);
break;
}
/* We don't want to push the extra child on any report list. */
Py_XDECREF (var->pretty_printer);
var->pretty_printer = visualizer;
- delete var->child_iter;
- var->child_iter = NULL;
+ var->child_iter.reset (nullptr);
}
/* Install the default visualizer for VAR. */
}
/* Install the given variable VAR with the object name VAR->OBJ_NAME. */
-static bool
+static void
install_variable (struct varobj *var)
{
hashval_t hash = htab_hash_string (var->obj_name.c_str ());
/* If root, add varobj to root list. */
if (is_root_p (var))
rootlist.push_front (var->root);
-
- return true; /* OK */
}
/* Uninstall the object VAR. */
htab_remove_elt_with_hash (varobj_table, var->obj_name.c_str (), hash);
if (varobjdebug)
- fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name.c_str ());
+ gdb_printf (gdb_stdlog, "Deleting %s\n", var->obj_name.c_str ());
/* If root, remove varobj from root list. */
if (is_root_p (var))
struct varobj_item item;
std::swap (item.name, name);
- item.value = value_of_child (parent, index);
+ item.value = release_value (value_of_child (parent, index));
return create_child_with_value (parent, index, &item);
}
if (item->value != NULL)
/* If the child had no evaluation errors, var->value
will be non-NULL and contain a valid type. */
- child->type = value_actual_type (item->value, 0, NULL);
+ child->type = value_actual_type (item->value.get (), 0, NULL);
else
/* Otherwise, we must compute the type. */
child->type = (*child->root->lang_ops->type_of_child) (child->parent,
child->index);
- install_new_value (child, item->value, 1);
+ install_new_value (child, item->value.get (), 1);
return child;
}
}
#endif
- delete var->dynamic->child_iter;
- varobj_clear_saved_item (var->dynamic);
+ /* This must be deleted before the root object, because Python-based
+ destructors need access to some components. */
+ delete var->dynamic;
if (is_root_p (var))
delete var->root;
-
- delete var->dynamic;
}
/* Return the type of the value that's stored in VAR,
{
CORE_ADDR pc = get_frame_pc (fi);
- if (pc < BLOCK_START (var->root->valid_block) ||
- pc >= BLOCK_END (var->root->valid_block))
+ if (pc < var->root->valid_block->start () ||
+ pc >= var->root->valid_block->end ())
scope = false;
else
select_frame (fi);
thevalue = std::string (s.get ());
len = thevalue.size ();
- gdbarch = get_type_arch (value_type (value));
+ gdbarch = value_type (value)->arch ();
type = builtin_type (gdbarch)->builtin_char;
if (!string_print)
/* If the THEVALUE has contents, it is a regular string. */
if (!thevalue.empty ())
- LA_PRINT_STRING (&stb, type, (gdb_byte *) thevalue.c_str (),
- len, encoding.get (), 0, &opts);
+ current_language->printstr (&stb, type, (gdb_byte *) thevalue.c_str (),
+ len, encoding.get (), 0, &opts);
else if (string_print)
/* Otherwise, if string_print is set, and it is not a regular
string, it is a lazy string. */
/* All other cases. */
common_val_print (value, &stb, 0, &opts, current_language);
- return std::move (stb.string ());
+ return stb.release ();
}
bool