Don't steal references in the gdb Python code

Some Python APIs steal references from their caller, and the refcount
checker supports this via an attribute.

However, in gdb with C++ we have a better idiom available: we can use
std::move on a gdbpy_ref<> instead.  This makes the semantics obvious
at the point of call, and is safer at runtime as well, because the
callee's gdbpy_ref<> will be emptied.

This patch changes the reference-stealing code in gdb to use rvalue
references instead.

Tested on x86-64 Fedora 28.

gdb/ChangeLog
2018-09-16  Tom Tromey  <tom@tromey.com>

	* python/python-internal.h (CPYCHECKER_STEALS_REFERENCE_TO_ARG):
	Remove.
	* python/py-varobj.c (py_varobj_iter_ctor): Change pyiter to
	rvalue reference.  Remove CPYCHECKER_STEALS_REFERENCE_TO_ARG.
	(py_varobj_iter_new): Likewise.
	(py_varobj_get_iterator): Use gdbpy_ref.
This commit is contained in:
Tom Tromey 2018-09-16 07:32:23 -06:00
parent 4a137fec2e
commit 1a3389079d
3 changed files with 17 additions and 16 deletions

View file

@ -1,3 +1,12 @@
2018-09-16 Tom Tromey <tom@tromey.com>
* python/python-internal.h (CPYCHECKER_STEALS_REFERENCE_TO_ARG):
Remove.
* python/py-varobj.c (py_varobj_iter_ctor): Change pyiter to
rvalue reference. Remove CPYCHECKER_STEALS_REFERENCE_TO_ARG.
(py_varobj_iter_new): Likewise.
(py_varobj_get_iterator): Use gdbpy_ref.
2018-09-16 Tom Tromey <tom@tromey.com> 2018-09-16 Tom Tromey <tom@tromey.com>
* python/py-threadevent.c (py_get_event_thread): Simplify. * python/py-threadevent.c (py_get_event_thread): Simplify.

View file

@ -130,14 +130,14 @@ static const struct varobj_iter_ops py_varobj_iter_ops =
whose children the iterator will be iterating over. PYITER is the whose children the iterator will be iterating over. PYITER is the
python iterator actually responsible for the iteration. */ python iterator actually responsible for the iteration. */
static void CPYCHECKER_STEALS_REFERENCE_TO_ARG (3) static void
py_varobj_iter_ctor (struct py_varobj_iter *self, py_varobj_iter_ctor (struct py_varobj_iter *self,
struct varobj *var, PyObject *pyiter) struct varobj *var, gdbpy_ref<> &&pyiter)
{ {
self->base.var = var; self->base.var = var;
self->base.ops = &py_varobj_iter_ops; self->base.ops = &py_varobj_iter_ops;
self->base.next_raw_index = 0; self->base.next_raw_index = 0;
self->iter = pyiter; self->iter = pyiter.release ();
} }
/* Allocate and construct a pretty-printed varobj iterator. VAR is /* Allocate and construct a pretty-printed varobj iterator. VAR is
@ -145,13 +145,13 @@ py_varobj_iter_ctor (struct py_varobj_iter *self,
PYITER is the python iterator actually responsible for the PYITER is the python iterator actually responsible for the
iteration. */ iteration. */
static struct py_varobj_iter * CPYCHECKER_STEALS_REFERENCE_TO_ARG (2) static struct py_varobj_iter *
py_varobj_iter_new (struct varobj *var, PyObject *pyiter) py_varobj_iter_new (struct varobj *var, gdbpy_ref<> &&pyiter)
{ {
struct py_varobj_iter *self; struct py_varobj_iter *self;
self = XNEW (struct py_varobj_iter); self = XNEW (struct py_varobj_iter);
py_varobj_iter_ctor (self, var, pyiter); py_varobj_iter_ctor (self, var, std::move (pyiter));
return self; return self;
} }
@ -161,7 +161,6 @@ py_varobj_iter_new (struct varobj *var, PyObject *pyiter)
struct varobj_iter * struct varobj_iter *
py_varobj_get_iterator (struct varobj *var, PyObject *printer) py_varobj_get_iterator (struct varobj *var, PyObject *printer)
{ {
PyObject *iter;
struct py_varobj_iter *py_iter; struct py_varobj_iter *py_iter;
gdbpy_enter_varobj enter_py (var); gdbpy_enter_varobj enter_py (var);
@ -177,14 +176,14 @@ py_varobj_get_iterator (struct varobj *var, PyObject *printer)
error (_("Null value returned for children")); error (_("Null value returned for children"));
} }
iter = PyObject_GetIter (children.get ()); gdbpy_ref<> iter (PyObject_GetIter (children.get ()));
if (iter == NULL) if (iter == NULL)
{ {
gdbpy_print_stack (); gdbpy_print_stack ();
error (_("Could not get children iterator")); error (_("Could not get children iterator"));
} }
py_iter = py_varobj_iter_new (var, iter); py_iter = py_varobj_iter_new (var, std::move (iter));
return &py_iter->base; return &py_iter->base;
} }

View file

@ -38,13 +38,6 @@
#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(ARG) #define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(ARG)
#endif #endif
#ifdef WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE
#define CPYCHECKER_STEALS_REFERENCE_TO_ARG(n) \
__attribute__ ((cpychecker_steals_reference_to_arg (n)))
#else
#define CPYCHECKER_STEALS_REFERENCE_TO_ARG(n)
#endif
#ifdef WITH_CPYCHECKER_SETS_EXCEPTION_ATTRIBUTE #ifdef WITH_CPYCHECKER_SETS_EXCEPTION_ATTRIBUTE
#define CPYCHECKER_SETS_EXCEPTION __attribute__ ((cpychecker_sets_exception)) #define CPYCHECKER_SETS_EXCEPTION __attribute__ ((cpychecker_sets_exception))
#else #else