Index: gdb/python/py-value.c |
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c |
index 19423eaf532127ed9bdaf3e776b759f549a5b111..6f67bdb2eb7ddc989714b2469ec775a103edd701 100644 |
--- a/gdb/python/py-value.c |
+++ b/gdb/python/py-value.c |
@@ -1,6 +1,6 @@ |
/* Python interface to values. |
- Copyright (C) 2008-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -28,6 +28,7 @@ |
#include "infcall.h" |
#include "expression.h" |
#include "cp-abi.h" |
+#include "python.h" |
#ifdef HAVE_PYTHON |
@@ -150,7 +151,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) |
} |
value_obj->value = value; |
- value_incref (value); |
+ release_value_or_incref (value); |
value_obj->address = NULL; |
value_obj->type = NULL; |
value_obj->dynamic_type = NULL; |
@@ -174,23 +175,68 @@ preserve_python_values (struct objfile *objfile, htab_t copied_types) |
static PyObject * |
valpy_dereference (PyObject *self, PyObject *args) |
{ |
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */ |
volatile struct gdb_exception except; |
+ PyObject *result = NULL; |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct value *res_val; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ |
res_val = value_ind (((value_object *) self)->value); |
+ result = value_to_value_object (res_val); |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- return value_to_value_object (res_val); |
+ return result; |
+} |
+ |
+/* Given a value of a pointer type or a reference type, return the value |
+ referenced. The difference between this function and valpy_dereference is |
+ that the latter applies * unary operator to a value, which need not always |
+ result in the value referenced. For example, for a value which is a reference |
+ to an 'int' pointer ('int *'), valpy_dereference will result in a value of |
+ type 'int' while valpy_referenced_value will result in a value of type |
+ 'int *'. */ |
+ |
+static PyObject * |
+valpy_referenced_value (PyObject *self, PyObject *args) |
+{ |
+ volatile struct gdb_exception except; |
+ PyObject *result = NULL; |
+ |
+ TRY_CATCH (except, RETURN_MASK_ALL) |
+ { |
+ struct value *self_val, *res_val; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ |
+ self_val = ((value_object *) self)->value; |
+ switch (TYPE_CODE (check_typedef (value_type (self_val)))) |
+ { |
+ case TYPE_CODE_PTR: |
+ res_val = value_ind (self_val); |
+ break; |
+ case TYPE_CODE_REF: |
+ res_val = coerce_ref (self_val); |
+ break; |
+ default: |
+ error(_("Trying to get the referenced value from a value which is " |
+ "neither a pointer nor a reference.")); |
+ } |
+ |
+ result = value_to_value_object (res_val); |
+ do_cleanups (cleanup); |
+ } |
+ GDB_PY_HANDLE_EXCEPTION (except); |
+ |
+ return result; |
} |
/* Return "&value". */ |
static PyObject * |
valpy_get_address (PyObject *self, void *closure) |
{ |
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */ |
value_object *val_obj = (value_object *) self; |
volatile struct gdb_exception except; |
@@ -198,15 +244,19 @@ valpy_get_address (PyObject *self, void *closure) |
{ |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct value *res_val; |
+ struct cleanup *cleanup |
+ = make_cleanup_value_free_to_mark (value_mark ()); |
+ |
res_val = value_addr (val_obj->value); |
+ val_obj->address = value_to_value_object (res_val); |
+ do_cleanups (cleanup); |
} |
if (except.reason < 0) |
{ |
val_obj->address = Py_None; |
Py_INCREF (Py_None); |
} |
- else |
- val_obj->address = value_to_value_object (res_val); |
} |
Py_XINCREF (val_obj->address); |
@@ -248,6 +298,7 @@ valpy_get_dynamic_type (PyObject *self, void *closure) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
struct value *val = obj->value; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
type = value_type (val); |
CHECK_TYPEDEF (type); |
@@ -277,6 +328,8 @@ valpy_get_dynamic_type (PyObject *self, void *closure) |
/* Re-use object's static type. */ |
type = NULL; |
} |
+ |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
@@ -311,7 +364,7 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) |
struct value *value = ((value_object *) self)->value; |
const char *user_encoding = NULL; |
static char *keywords[] = { "encoding", "length", NULL }; |
- PyObject *str_obj; |
+ PyObject *str_obj = NULL; |
volatile struct gdb_exception except; |
if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords, |
@@ -320,16 +373,20 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ |
if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR) |
value = value_ind (value); |
+ |
+ str_obj = gdbpy_create_lazy_string_object (value_address (value), length, |
+ user_encoding, |
+ value_type (value)); |
+ |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- str_obj = gdbpy_create_lazy_string_object (value_address (value), length, |
- user_encoding, |
- value_type (value)); |
- |
- return (PyObject *) str_obj; |
+ return str_obj; |
} |
/* Implementation of gdb.Value.string ([encoding] [, errors] |
@@ -376,9 +433,8 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw) |
static PyObject * |
valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op) |
{ |
- PyObject *type_obj; |
+ PyObject *type_obj, *result = NULL; |
struct type *type; |
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */ |
volatile struct gdb_exception except; |
if (! PyArg_ParseTuple (args, "O", &type_obj)) |
@@ -395,6 +451,8 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
struct value *val = ((value_object *) self)->value; |
+ struct value *res_val; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
if (op == UNOP_DYNAMIC_CAST) |
res_val = value_dynamic_cast (type, val); |
@@ -405,10 +463,13 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op) |
gdb_assert (op == UNOP_CAST); |
res_val = value_cast (type, val); |
} |
+ |
+ result = value_to_value_object (res_val); |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- return value_to_value_object (res_val); |
+ return result; |
} |
/* Implementation of the "cast" method. */ |
@@ -451,8 +512,8 @@ valpy_getitem (PyObject *self, PyObject *key) |
{ |
value_object *self_value = (value_object *) self; |
char *field = NULL; |
- struct value *res_val = NULL; |
volatile struct gdb_exception except; |
+ PyObject *result = NULL; |
if (gdbpy_is_string (key)) |
{ |
@@ -464,6 +525,8 @@ valpy_getitem (PyObject *self, PyObject *key) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
struct value *tmp = self_value->value; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ struct value *res_val = NULL; |
if (field) |
res_val = value_struct_elt (&tmp, NULL, field, 0, NULL); |
@@ -489,12 +552,16 @@ valpy_getitem (PyObject *self, PyObject *key) |
res_val = value_subscript (tmp, value_as_long (idx)); |
} |
} |
+ |
+ if (res_val) |
+ result = value_to_value_object (res_val); |
+ do_cleanups (cleanup); |
} |
xfree (field); |
GDB_PY_HANDLE_EXCEPTION (except); |
- return res_val ? value_to_value_object (res_val) : NULL; |
+ return result; |
} |
static int |
@@ -510,12 +577,13 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value) |
static PyObject * |
valpy_call (PyObject *self, PyObject *args, PyObject *keywords) |
{ |
- struct value *return_value = NULL; |
Py_ssize_t args_count; |
volatile struct gdb_exception except; |
struct value *function = ((value_object *) self)->value; |
struct value **vargs = NULL; |
struct type *ftype = NULL; |
+ struct value *mark = value_mark (); |
+ PyObject *result = NULL; |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
@@ -558,11 +626,16 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark); |
+ struct value *return_value; |
+ |
return_value = call_function_by_hand (function, args_count, vargs); |
+ result = value_to_value_object (return_value); |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- return value_to_value_object (return_value); |
+ return result; |
} |
/* Called by the Python interpreter to obtain string representation |
@@ -687,12 +760,14 @@ enum valpy_opcode |
static PyObject * |
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) |
{ |
- struct value *res_val = NULL; /* Initialize to appease gcc warning. */ |
volatile struct gdb_exception except; |
+ PyObject *result = NULL; |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
struct value *arg1, *arg2; |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ struct value *res_val = NULL; |
/* If the gdb.Value object is the second operand, then it will be passed |
to us as the OTHER argument, and SELF will be an entirely different |
@@ -778,10 +853,15 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) |
res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR); |
break; |
} |
+ |
+ if (res_val) |
+ result = value_to_value_object (res_val); |
+ |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- return res_val ? value_to_value_object (res_val) : NULL; |
+ return result; |
} |
static PyObject * |
@@ -833,16 +913,22 @@ valpy_power (PyObject *self, PyObject *other, PyObject *unused) |
static PyObject * |
valpy_negative (PyObject *self) |
{ |
- struct value *val = NULL; |
volatile struct gdb_exception except; |
+ PyObject *result = NULL; |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ /* Perhaps overkill, but consistency has some virtue. */ |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ struct value *val; |
+ |
val = value_neg (((value_object *) self)->value); |
+ result = value_to_value_object (val); |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
- return value_to_value_object (val); |
+ return result; |
} |
static PyObject * |
@@ -860,8 +946,12 @@ valpy_absolute (PyObject *self) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); |
+ |
if (value_less (value, value_zero (value_type (value), not_lval))) |
isabs = 0; |
+ |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
@@ -961,7 +1051,6 @@ static PyObject * |
valpy_richcompare (PyObject *self, PyObject *other, int op) |
{ |
int result = 0; |
- struct value *value_other; |
volatile struct gdb_exception except; |
if (other == Py_None) |
@@ -985,6 +1074,9 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
+ struct value *value_other, *mark = value_mark (); |
+ struct cleanup *cleanup; |
+ |
value_other = convert_value_from_python (other); |
if (value_other == NULL) |
{ |
@@ -992,6 +1084,8 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) |
break; |
} |
+ cleanup = make_cleanup_value_free_to_mark (mark); |
+ |
switch (op) { |
case Py_LT: |
result = value_less (((value_object *) self)->value, value_other); |
@@ -1020,6 +1114,8 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) |
result = -1; |
break; |
} |
+ |
+ do_cleanups (cleanup); |
} |
GDB_PY_HANDLE_EXCEPTION (except); |
@@ -1123,7 +1219,7 @@ value_to_value_object (struct value *val) |
if (val_obj != NULL) |
{ |
val_obj->value = val; |
- value_incref (val); |
+ release_value_or_incref (val); |
val_obj->address = NULL; |
val_obj->type = NULL; |
val_obj->dynamic_type = NULL; |
@@ -1154,7 +1250,6 @@ struct value * |
convert_value_from_python (PyObject *obj) |
{ |
struct value *value = NULL; /* -Wall */ |
- struct cleanup *old; |
volatile struct gdb_exception except; |
int cmp; |
@@ -1223,6 +1318,8 @@ convert_value_from_python (PyObject *obj) |
s = python_string_to_target_string (obj); |
if (s != NULL) |
{ |
+ struct cleanup *old; |
+ |
old = make_cleanup (xfree, s); |
value = value_cstring (s, strlen (s), builtin_type_pychar); |
do_cleanups (old); |
@@ -1324,6 +1421,8 @@ Cast the value to the supplied type, as if by the C++\n\ |
reinterpret_cast operator." |
}, |
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, |
+ { "referenced_value", valpy_referenced_value, METH_NOARGS, |
+ "Return the value referenced by a TYPE_CODE_REF or TYPE_CODE_PTR value." }, |
{ "lazy_string", (PyCFunction) valpy_lazy_string, |
METH_VARARGS | METH_KEYWORDS, |
"lazy_string ([encoding] [, length]) -> lazy_string\n\ |